Activity与Fragment之间生命周期比较
- http://blog.csdn.net/chun0801/article/details/51956847
- Activity于Fragment的生命周期的不同主要表现在onCreate和onDestroy两个生命周期方法中:
- 在Activity的onCreate方法回调时,在回调期间,Fragment首先会执行
onAttach()-->onCreate()-->onCreateView()-->onActivityCreated() - 在Activity的onDestroy()回调时,在回调期间,Fragment首先会执行onDestroyView()-->onDestroy()-->onDetach()
- 在Activity的onCreate方法回调时,在回调期间,Fragment首先会执行
Arraylist 与 Linkedlist 异同?
- http://www.cnblogs.com/janneystory/p/5758958.html
- Arraylist与LinkedList的差异主要是因为实现的不同导致的性能差异以及不同的适用场景:
- Arraylist是基于动态数组实现,Linkedlist基于链表实现。
- 由于Arraylist是基于数组,得益于数组的随机高效访问,也同样具备随机访问的良好表现,适用于对List数据集的访问次数远大于存储和删除数据次数。而Linkedlist由于是链表,需要指针的移动,导致访问速度不如ArrayList,适用于存储数据的次数远大于读取数据的场景。
- 也同样受限于数组,Arraylist的数据存储和删除会涉及到数组的移动,会付出相对大的代价,导致性能下降。而Linkedlist由于是基于链表实现的双向链表,更新或者删除数据只需要更新附近的节点即可,不涉及数据的移动,所以性能要高于Arraylist。
MVP模式
- http://blog.csdn.net/lmj623565791/article/details/46596109
- MVP模式是一种代码的结构,是从MVC模式上面发展而来,用于在项目代码繁多,结构臃肿的情况下对代码的划分,MVC是传统的编程方式,其中Model、Controler和View之间呈三角形方式相互调用,界限模糊,几乎所有的代码都集中于Activity,需要测试的时候无从下手,扩展业务的时候没办法很快定位到功能代码,此时MVP应运而生,Model不再与View层有相互调用关系,全部以接口形式调用,由Presenter集中控制,使得代码结构清晰,测试时只需要重写为View定义的接口的测试实现类代替实际View传入Presenter进行测试即可,维护性和扩展性得到很大提升,测试也更方便,就是接口会增加很多,在大的项目中这是值得的!
App启动崩溃异常捕捉
- http://www.jianshu.com/p/fb28a5322d8a
- App启动崩溃异常捕捉:
即捕捉非受检异常(UnCheckException),也就是由于程序的错误造成的错误,无法挽回,只能关闭程序。是在程序发布后,用户手机上产生的崩溃异常需要传回开发者手中以便解决的一种手段:- 需要创建Thread.UncaughtExceptionHandler接口的实现类
- 调用Thread.getDefaultUncaughtExceptionHandler()获取系统的实现类实例保存,以备我们自定义的处理方法没有成功处理异常时再执行系统的处理逻辑
- 调用Thread.setDefaultUncaughtExceptionHandler(this)方法使用自定义的接口实现类代替系统实现
- 重写uncaughtException方法,拿到Throwable后实现自己的逻辑,譬如保存到硬盘,上传到服务器回馈给开发者
- System.exit(0)杀死进程(0表示正常结束,1表示异常关闭)
JVM 内存区域 开线程影响哪块内存
- http://www.cnblogs.com/wangjzh/p/5258254.html
- 堆:用于存储动态生成的对象和数组,其中对象的引用指针存放在虚拟机栈中,提供给线程引用,在线程执行完毕,虚拟机栈被回收,只是对堆中相应对象的引用没了,对象并不会被回收,只有在此对象不再有另外的引用时,并且在gc扫描到的时候才会被回收,这也是内存泄漏发生的地方
- 方法区:用于存储静态变量、常量和(JIT)即时编译产生的字节码,其中常量位于方法区内部的一个常量池,动态产生的常量也会放入常量池,例如String的intern方法
- 虚拟机栈:也称为方法栈,用于存储在方法运行期间产生的局部变量,包括方法的操作码,也就是方法的索引
- 本地方法栈:和虚拟机栈唯一不同的是,它针对的是native方法
- 程序计数器:这是一块较小的内存区域,是对当前线程字节码执行的位置指示器,分支、跳转、异常处理、循环和线程恢复等基础功能都需要依赖于程序计数器
- JVM内存区域分为线程共享区和非线程共享区:
- 线程共享区:堆、方法区
- 非线程共享区:虚拟机栈、本地方法栈、程序计数器
- 线程共享区是属于JVM所拥有,每一个程序有一个JVM,而每一个JVM有一份线程共享区,存在于整个程序运行期间
- 非线程共享区是属于每一条线程拥有,存在周期就是线程的运行周期,线程执行完毕就会被回收
- 所以开线程会影响到线程共享区,因为需要对线程需要的资源进行加载
如何保持应用的稳定性
- 所谓应用稳定性,也就是防止应用在使用过程中尽量少出现闪退、卡顿、流畅,尽量避免内存泄漏和内存溢出。要预防这一类问题,要从编写代码的时候就开始注意,主要分为以下几点:
- 四大组件方面:
- Activity:响应时间限制是5s,表现在不可以在主线程执行耗时操作,可以考虑使用开启子线程
- Broadcast:响应时间限制是10s,原因是onReceiver方法执行在主线程中,其中操作过于耗时,可以考虑开启Service,然后在Service中开启子线程执行
- Service:响应时间限制是20s,原因是Service默认运行在主线程中,需要开子线程执行操作
- 内存方面:
- OOM:当前申请的内存已经超过了虚拟机的可用内存
- 内存泄漏:分配出去的内存不再使用,却无法回收重复利用。解决方法主要是对每个对象的生命周期达到完美的控制
1. 图片方面:图片压缩,先加载缩略图,在滑动时不加载图片
2. 内部类设置为静态内部类,对外部类的引用使用弱引用,静态变量的生命周期过长
3. 在Activity的OnDestroy方法中做一些资源的回收操作 - 内存抖动:程序短时间内创建大量对象,然后回收的现
1. 一般出现在onDraw方法中,由于view的绘制可能会调用此方法多次,如果在此方法中创建对象,可能就出现短时间内大量对象被创建的现象,之后gc就会运行,回收对象,也就是内存抖动现象
- UI方面:UI的绘制帧数保持在60fps为最佳,这要求每帧的绘制时间不超过1000/60ms,也就是16ms左右一定要完成界面渲染,否则就会出现卡顿
- 卡顿原因:
1. UI线程,即主线程中执行了耗时操作
2. 布局过于复杂
3. 动画的执行次数过多
4. view重复的调用measure、layout方法 - 解决方案:
1. 使用include、viewstub、merge等标签减少布局层级
2. 布局太复杂考虑使用自定义View
3. 使用RecyclerView
4. 不要频繁绘制View
5. 使用多线程执行耗时操作
- 卡顿原因:
- 总结:对于网络上的资源,如图片、json数据,可以考虑使用缓存技术,懒加载技术,先显示出效果给用户,之后获取到数据再刷新,提供最好的体验;至于布局的层级的精简可以使用一些优化工具,编码可能导致的内存泄漏可以使用静态扫描工具如Findbugs等,编码的规则参考阿里规约。