Hander面试详解

作者: Skypew | 来源:发表于2017-11-15 11:01 被阅读40次

    一.什么是handler

    android中 只有主线程才能更新ui,handler通知ui更新 耗时操作,(文件读取,网络数据获取 )
    Message 传递的是消息 MessageQueue 消息队列

    image.png

    二.handler的使用方法

    image.png
    image.png
    image.png

    1.post(runnable)

    image.png

    post 最终调用的也是hander方法

    public class MainActivity extends BaseActicity {
    
        //hander 绑定的是ui线程 
        private Handler mHandler  = new Handler();
    
        public static void show(Context context) {
            context.startActivity(new Intent(context, MainActivity.class));
        }
    
        @Override
        protected int getContentLayoutId() {
            return R.layout.activity_main;
        }
    
    
        @Override
        protected void initWidget() {
            super.initWidget();
    
    
        }
    
    
        @Override
        protected void initData() {
            super.initData();
            //启动线程 
            DownLoadThread downLoadThread = new DownLoadThread();
            downLoadThread.start();
    
        }
    
       
        class  DownLoadThread  extends Thread{
            @Override
            public void run() {
                Logger.show("文件","开始下载");
                try {
                    Thread.sleep(5000);
                    Logger.show("文件","下载完成");
    
                    Runnable runable = new Runnable() {
                        @Override
                        public void run() {
                            //todo  可以在主线程 更新ui 
                            Logger.show("文件","下载完成");
                        }
                    };
                    //这里 执行的结果是在 UI线程 
                    mHandler.post(runable);
    
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
            }
        }
    }
    
    

    2.sendMessage(message)

    public class MainActivity extends BaseActicity {
    
      private Handler mHandler  = new Handler(){
            @Override
            public void handleMessage(Message msg) {
              switch (msg.what){
                  case 1:
                      // 进行ui操作
                      break;
              }
            }
        };
    
        public static void show(Context context) {
            context.startActivity(new Intent(context, MainActivity.class));
        }
    
        @Override
        protected int getContentLayoutId() {
            return R.layout.activity_main;
        }
    
    
    
        @Override
        protected void initData() {
            super.initData();
    
            DownLoadThread downLoadThread = new DownLoadThread();
            downLoadThread.start();
    
        }
    
    
        class  DownLoadThread  extends Thread{
            @Override
            public void run() {
                Logger.show("文件","开始下载");
                try {
                    Thread.sleep(5000);
                    Logger.show("文件","下载完成");
    
                    Message msg = new Message();
                  //  msg = Message.obtain();
                //产生一个Message对象,可以new  ,也可以使用Message.obtain()方法;两者都可以,但是更建议使用obtain方法,因为Message内部维护了一个Message池用于Message的复用,避免使用new 重新分配内存。
                    msg.what=1;
                  //  msg.arg1
    
                    mHandler.sendMessage(msg);
    
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
    
            }
        }
    
    
    

    三. hander 机制的原理

    参考博文 :Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系http://blog.csdn.net/lmj623565791/article/details/38377229

    Handler 、 Looper 、Message 这三者都与Android异步消息处理线程相关的概念

    那么什么叫异步消息处理线程呢?
    异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环。若消息队列为空,线程则会阻塞等待。

    其实Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息,而消息的创建者就是一个或多个Handler 。


    image.png

    Handler不仅可以更新UI,你完全可以在一个子线程中去创建一个Handler,然后使用这个handler实例在任何其他线程中发送消息,最终处理消息的代码都会在你创建Handler实例的线程中运行。

    mHandler = new Handler(context.getMainLooper()) 运行在主线程

    class LooperThread extends Thread {  
          public Handler mHandler;  
      
          public void run() {  
              Looper.prepare();  
      
              mHandler = new Handler() {  
                  public void handleMessage(Message msg) {  
                      // process incoming messages here  
                  }  
              };  
      
              Looper.loop();  
          }  
      }  
    

    四.hander引起的内存泄漏和解决办法

    创建hander 不是静态内部类 会隐匿持有外部activity对象

    image.png

    解决方法:

    1. 把hander 定义为静态内部类
    如果需要调用activity 需要使用弱引用的方式
    1. mHandler.removeCallbacks(Thread);
    public class HandlerActivity extends AppCompatActivity {
    
      private final static int MESSAGECODE = 1 ;
      private static Handler handler ;
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler);
    
        findViewById( R.id.finish ).setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            finish();
          }
        });
    
        //创建Handler
        handler = new MyHandler( this ) ;
    
        //创建线程并且启动线程
        new Thread( new MyRunnable() ).start();
      }
    
      private static class MyHandler extends Handler {
        WeakReference<HandlerActivity> weakReference ;
    
        public MyHandler(HandlerActivity activity ){
          weakReference = new WeakReference<HandlerActivity>( activity) ;
        }
    
        @Override
        public void handleMessage(Message msg) {
          super.handleMessage(msg);
          if ( weakReference.get() != null ){
            // update android ui
            Log.d("mmmmmmmm" , "handler " + msg.what ) ;
          }
        }
      }
    
      private static class MyRunnable implements Runnable {
    
        @Override
        public void run() {
          handler.sendEmptyMessage( MESSAGECODE ) ;
          try {
            Thread.sleep( 8000 );
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          handler.sendEmptyMessage( MESSAGECODE ) ;
        }
      }
    
      @Override
      protected void onDestroy() {
        super.onDestroy();
    
        //如果参数为null的话,会将所有的Callbacks和Messages全部清除掉。
        handler.removeCallbacksAndMessages( null );
      }
    }
    
    
    

    相关文章

      网友评论

        本文标题:Hander面试详解

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