摘要:
- 关于JVM:懒汉式单例、饿汉式单例和静态内部类单例有什么区别?
- 关于JVM:Java虚拟机有自动垃圾回收机制,为什么还会出现内存泄露?内存泄露和OOM有什么关系?
- Fragment和View有什么区别,为什么使用Fragment?
- Fragment和Activity有什么区别,为什么使用Fragment?
- Fragment挂载的Activity销毁后,Fragment是否还存在?
- 在Activity的
onCreate
方法中使用Handler延时5s执行DialogFragment.show()
代码,这时候按下Home键会怎样? - 判断一条单链表是否成环,代码实现
- 说一下View包含哪些生命周期
- 一个apk由哪几个文件夹组成以及每个文件夹的作用?
- Kotlin比Java有什么优势?
- Service更新UI,有哪几种方式
- 有60张1920x1080的图片做成滚动动画效果,一秒内播放15张,如何保证流畅性?
问题一
这是一道深入理解虚拟机的题目,类被虚拟机加载阶段,会将二进制流中的静态存储结构转换成方法区的运行时数据结构,在内存中生成代表这个类的java.lang.Class
对象,作为访问这个类的各种数据的入口。类的准备阶段为类变量分配内存并设置类变量的初始值,使用的内存将在方法区进行分配。
- 饿汉式单例,是一个静态的存储结构,类被加载后在准备阶段类变量被分配内存,遇到new关键字完成初始化,初始化是在类被加载的过程中。饿汉式的特点:线程安全的,类在加载过程分配了内存,速度更快。如果某些单例实际没有被使用到,这种创建单例方式会造成额外的内存开销。
- 懒汉式单例,调用
getInstance()
方法开始完成初始化,初始化是在类的构造方法中,是非线程安全的,在初始化内容较多的情况下,可能造成延时,同时在调用的时候分配堆内存,减少内存的浪费。 - 静态内部类单例,和懒汉式类似,在调用的时候开始分配内存,减少内存的浪费。区别:静态内部类是线程安全的
问题二
垃圾收集器常用的算法有:计数收集器,追踪收集器,压缩收集器,拷贝收集器,按代收集的收集器,自动收集器等,能够被收集的对象需要满足一定的规则,比如:不再持有强引用,将引用置null,一个对象在销毁前还被引用,垃圾收集器认为这是活动的对象,无法满足算法规则,造成内存泄露。
过多的内存泄露会造成内存溢出。
自动垃圾回收机制,需要编程人员写书更符合算法的代码,降低内存销毁,避免内存泄露,同时也要注意频繁地垃圾回收也可能造成额外的性能开销,内存抖动。
问题三
- Fragment和View都需要挂载到Activity中,不能独立存在
- Fragment和View拥有各自的生命周期,Fragment的生命周期更丰富,比如:
onAttach(Context)
、onCreate()
、onCreateView()
、onViewCreated()
、onActivityCreate()
等 - Fragment实例化后可以添加到回退栈中,使用
addToBackStack()
方法后,Fragment不会被销毁 - Fragment可以获取界面之间跳转传递的通信信息,比如:Activity跳转,Fragment切换
- Fragment应用于碎片化处理,组合成一个大屏幕,每个Fragment负责独立的功能模块,方便管理和方便复用
- Fragment提供更丰富的方法管理视图交换,比如:
onHiddenChanged()
、setUserVisibleHint(boolean)
- Fragment通过事务操作,保证操作的原子性,提供丰富的方法:
replace()
、remove()
、add()
、hide()
、show()
、attach()
、detach()
- Fragment用于各种更复杂的界面交互,简单的界面使用View
- Fragment在Activity异常退出(旋转屏幕),重启后创建新的FragmentManager,并获取保存下来的Fragment队列,恢复保存的状态信息
- View是无状态的,Activity异常退出(旋转屏幕),View需要重新初始化;
- View中用户交互、界面更新等相关代码全部写到Activity中,想得臃肿,不方便扩展
- View和Activity同生死,Fragment在创建后,Activity退出依然存活
问题四
- Fragment方便被多个Activity复用
- Fragment初始化占据的内存比Activity少,初始化后响应速度更快
- Fragment可以用来代替Activity,反之则不可以
- Fragment模块化管理,降低耦合度,方便UI更新和扩展
- Fragment初始化后,添加到回退栈,方便重用
- Fragment提供更新丰富的事务操作方法:
replace()
、remove()
、add()
、hide()
、show()
- Fragment可以添加到布局文件中,也可以在代码中动态使用,Activity则不可以
- Fragment使用不需要在清单文件中配置组件信息
- Fragment搭载ViewPager、TabHost实现更丰富的界面效果
- Fragment不可以在后台运行,Activity销毁后,创建的Fragment仍可以存活,这时候需要注意
getActivity()
返回null - Fragment在异常退出(旋转屏幕),Fragment被销毁,可以保存状态信息,重启后可以恢复原来的状态
问题五
Fragment执行onAttach()
方法挂载到Activity中,Activity销毁后执行onDetach()
解除挂载,这时候已创建的Fragment不会仍然存活。
重启Activity后,创建新的FragmentManager,并获取保存下来的Fragment队列,恢复保存的状态信息
这样,避免重复创建Fragment的内存开销。
问题六
Fragment无法在后台运行。
Activity初始化后,按钮Home键,Activity进入了后台,这个时候延时5s执行DialogFragment.show()
方法,会崩溃退出!
原因:Fragment无法在后台运行,Activity进入后台后,Fragment无法执行其完整的生命周期方法,比如:onAttach()
、onCreate()
,这时候执行DialogFragment.show
,程序会异常退出。
问题七
Node
表示一条单链表,这里省略了单例的创建过程,详情参考《Java常用数据结构》,识别是否成环的核心代码:
boolean loopSingleList(Node node){
//如果node为null或下一个节点为null,非循环链表
if(node==null||node.next==null) return false;
Node p1=node;
Node p2=node;
Node last=null;
while((last=p2.next)!=null&&(last.next!=null)){
p1=p1.next;//每次移动一步
p2=last.next;//每次移动两步
if(p1==p2) return true;//p1等于p2,成环
return false;//默认不成环
}
}
问题八
View的生命周期包括:创建、挂载、布局、事件、焦点,如下图:
问题九
META-INF
,存放签名信息,保证apk文件的完整性和系统安全lib
,如果存在的话,存NDK编译出来的so文件res
,存放anim、color、drawable、layout等资源文件,编译时会自动在R.java中生成索引文件assets
,存放原始资源文件,需要使用AssetManager来访问目录文件resources.arsc
,存放编译后的二进制资源文件classes.dex
,将编译生成的.class文件转换成dalvik字节码文件AndroidManifest.xml
,存放程序全局配置信息
问题十
- Kotlin 定义变量,可以省略变量类型,JVM自动根据赋值情况确定类型
- Kotlin 定义变量更加方便,用到
val
、var
两个关键字 - Kotlin 定义变量和函数更加方便,不需要指定变量、函数的作用域
- Kotlin 定义函数统一使用关键字
fun
- Kotlin 定义的函数可以作为形参传递,也可以作为返回值传递
- Kotlin 提供了更方便的运算符:可空类型(
?
)、安全调用运算符(?.
)、安全转换运算符(as?
)、null合并运算符(?:
)和let
运算符 - Kotlin 创建类简化了代码量,继承类或实现接口统一使用冒号(
:
) - Kotlin 定义接口,运行添加默认的实现
- Kotlin 初始化对象,不再需要关键字
new
- Kotlin 类和方法默认都是final,不允许被继承,不允许被重写
- Kotlin 使用
open
关键字定义一个类运行继承,使用open
关键字定义一个方法运行被重写 - Kotlin 接口不能使用关键字
final
、open
或abstract
,接口的成员始终都是open
- Kotlin 省略修饰符,声明就是
public
- Kotlin 声明的内部类没有显示添加修饰符,默认为嵌套类;使用
inner
修饰符声明为内部类
问题十一
- 广播,
onReceive()
方法中不适合做耗时的操作 Messenger
,跨进程通信,实现Service跨进程更新UI界面bindService
,重写ServiceConnection
接口方法,在服务连接或服务断开时做更新UI的操作Service
子类中传入Handler或Activity的引用,使用Handler发送消息到UI界面,在Handler的handleMessage()
接收消息并更新UI
问题十二
- 预加载本地图片转成Bitmap,使用
LruCache
进行缓存,设置将图片占据的内存大小并维持在一定范围内 - 依次从
LruCache
读取需要展示的图片,内存不足的情况下会清除最近使用最少的Bitmap对象 - 同时开启子线程在清除某个Bitmap对象的同时预加载另一个Bitmap对象存入
LruCache
中 - 循环执行:预加载——>展示——>清除——>预加载,保证展示动画的流畅性,同时防止OOM
附件:
你可能感兴趣的文章
转载请注明出处: https://www.teachcourse.cn/2763.html ,谢谢支持!