美文网首页
异步消息处理机制相关面试题

异步消息处理机制相关面试题

作者: 一生有你_b4f6 | 来源:发表于2018-08-17 14:08 被阅读0次

一.Handler的四大组件和运作机制

    handler其实就是androidSDK提供给我们开发者方便进行异步消息处理的类

    例如,asynctask,retrofit都是封装了handler

    注意:

    1.每一给线程只能有一个looper,主线程中创建looper,并且在looper内创建messagequeue

    2.Looper类主要是为每个线程开启的单独的消息循环

    3.messagequeue通过looper来管理message

    4.messagequeue利用先进先出的原理来处理message

    5.handler的作用就是发送消息和处理消息

    6.handler是looper的一个接口

    7.在非主线程中直接new Handler是不可以,除非先创建Looper的对象

整体流程:创建handler的时候回获取到当前线程的looper,然后通过这个looper获取到这个消息队列meessagequeue,然后通过handler来发送消息message,将message发送到消息队列messagequeue,然后再通过looper轮询消息队列取出消息再交给handler处理,这个时候再handler里面的handlermessage方法

     1>在什么情况下使用handler会造成内存泄露

private Handler handler =new Handler(){

      public void handleMessage(android.os.Message msg){

            if(msg.what == 1){               

                 noteBookAdapter.notifyDataSetChanged();            

             }        

    } 

};

上面是一段简单的Handler的使用。当使用内部类(包括匿名类)来创建Handler的时候,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用(不然你怎么可能通过Handler来操作Activity中的View?)。而Handler通常会伴随着一个耗时的后台线程(例如从网络拉取图片)一起出现,这个后台线程在任务执行完毕(例如图片下载完毕)之后,通过消息机制通知Handler,然后Handler把图片更新到界面。然而,如果用户在网络请求过程中关闭了Activity,正常情况下,Activity不再被使用,它就有可能在GC检查时被回收掉,但由于这时线程尚未执行完,而该线程持有Handler的引用(不然它怎么发消息给Handler?),这个Handler又持有Activity的引用,就导致该Activity无法被回收(即内存泄露),直到网络请求结束(例如图片下载完毕)。另外,如果你执行了Handler的postDelayed()方法,该方法会将你的Handler装入一个Message,并把这条Message推到MessageQueue中,那么在你设定的delay到达之前,会有一条MessageQueue -> Message -> Handler -> Activity的链,导致你的Activity被持有引用而无法被回收。

    2>如何解决因为handler所引起的内存泄露

方法一:通过程序逻辑来进行保护。

1.在关闭Activity的时候停掉你的后台线程。线程停掉了,就相当于切断了Handler和外部连接的线,Activity自然会在合适的时候被回收。 

2.如果你的Handler是被delay的Message持有了引用,那么使用相应的Handler的removeCallbacks()方法,把消息对象从消息队列移除就行了。

方法二:将Handler声明为静态类。

在Java 中,非静态的内部类和匿名内部类都会隐式地持有其外部类的引用,静态的内部类不会持有外部类的引用。

静态类不持有外部类的对象,所以你的Activity可以随意被回收。由于Handler不再持有外部类对象的引用,导致程序不允许你在Handler中操作Activity中的对象了。所以你需要在Handler中增加一个对Activity的弱引用(WeakReference)。

二.AsyncTask

    1.Handler+线程池的封装

        1>onPreExecute()----->运行在UI线程中,在调用DoInBackground()之前执行,可以做初始化操作

        2>doInbackground()----->后台运行,非UI线程,可以执行耗时方法

        3>onPostExecute()------>运行在UI线程中,在doinbackground()执行完毕后执行

        4>onProgressUpdate()----->在publishProgress()被调用后执行,publishProgress()用于更新进度,在UI线程中执行

    注意要点:

          1>AsyncTask的实例必须在主线程中创建

           2>AsyncTask的excute方法必须在主线程中调用

            3>回调方法,android会自动调用

            4>一个AsyncTack的实例,只能执行一次execute方法

相关文章

网友评论

      本文标题:异步消息处理机制相关面试题

      本文链接:https://www.haomeiwen.com/subject/rjizbftx.html