Android Handler常见问题

      Handler 作为Android中最常用的类,主要负责线程间通信。

      相关联的类有Looper, MessageQueue, Message;这篇主要记录一下Handler导致内存泄漏,以及一些常见的问题。

一. Handler 导致的内存泄漏

       内存泄漏的现象是不再需要的对象无法被GC回收;例如一个Activity已经退出了,却无法被GC回收,严重时会导致OOM。

       Handler导致内存泄漏的原因是如果在Activity内部通过new一个非静态匿名类的方式创建了Handler对象,那么该Handler对象会隐式持有对Activity的引用(JAVA中非静态内部类持有对外部类引用);那么如果Activity销毁而Handler中的消息还未处理,会导致Handler对象持有对Activity的引用,导致Activity无法释放而内存泄漏。

       有朋友说在Activity退出的时候调用 Handler的 removeCallbacksAndMessages 移除消息即可,这种方式的确可以减少Activity退出后Handler对象继续执行 handlerMessage 带来的系统开销,但并没有解决上面提到的内存泄漏问题;原因是handler发送Message对象到MessageQueue中,Mesaage对象中的target会持有发送该消息的Handler对象的引用,如果Meassage对象对Handler的引用存在,那么Handler对象就无法被回收,导致Activity无法被回收而内存泄漏。

解决方法是

       1. 将Handler定义为静态的,因为静态内部类不会持有对外部类的引用

        2. 定义为静态内部类后,Handler对于外部类Activity中成员变量的操作,通过Handler构造函数中传入Activity对象来实现,然后用弱引用包裹传入的Activity对象,保证每次在GC时Activity对象会被回收。

        通过上述两步可以确保使用Handler时Activity不会存在内存泄漏的问题。上述方案是原理,实际使用时会通过封装来简化使用,避免每次都去定义一个静态的Handler。

二. Looper 无限循环相关问题

       Looper是一个无线循环,那么主线程的Looper是否会导致主线程阻塞,引起ANR?

       这是一个相对高级的面试问题,答案显然是否定的,但想回答好需要梳理一下。

       精简的回答是: 安卓的主线程通过Looper无限循环来保证主线程不会刚启动就退出,否则主线程退出进程也就退出了;而我们操作时ANR的问题是因为在Activity, Service,BroadcastReceiver中不应该执行耗时操作的回调中,运行了耗时代码超时导致ANR。

        其中的原理是系统会有一个System Server进程; 在应用层的 APP进程运行时,主线程的Activity的onCreate,onResume,onPause等回调都是系统的System Server进程通过Binder通信传递给APP进程,最后消息传递到主线程执行相应的回调,这个过程中不存在ANR的问题,而如果在APP进程收到回调消息,例如在 onCreate中执行了耗时操作超过了一定时间后出现ANR。

发布了11 篇原创文章 · 获赞 2 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/zhengyin_tmac/article/details/105056653
今日推荐