"Android-事件处理机制"之面试必问技能点汇总

一.Handler机制

安卓把UI和耗时操作分在不同线程的原因:

  • 为了保证UI线程流程性
    • 手机显示的刷新频路:60Hz,即1秒60次,每16.67毫秒刷一次,为了不丢帧,那么主线程处理代码最好不要超过16毫秒.
    • 当子线程处理完耗时才走后,为了防止UI线程处理逻辑的混乱,就通过Handler来充当主线程和子线程间的桥梁.

逻辑:

  • 1.Handler在主线程Activity
  • 2.复写Handler的HandlerMessage方法
  • 3.子线程通过调用handler.sendMessage(),主线程就会执行HandlderMessage方法

完整的Handler机制,参数的讲解:

  • 1.除了Handler,Message,还有隐藏的Looper和MessageQueue对象
  • 2.主线程默认调用Looper.preper()方法;
    • 目的:在Looper里创建MessageQueue成员变量,且吧Looper对象绑定到当前线程
    • 当调用Handler 的sendMessage(对象)方法,就将Message对象添加到了Looper创建的MessageQueue队列中,同时给Message指定了target 对象.
      (PS:target对象就是 Handler 对象)
  • 3.主线程也默认执行Looper.looper()方法,该方法从Looper成员变量的MessageQueue中取出Message
    • 然后调用Message的targe对象的handleMessage()方法

(点击访问图解内容)

可以再谈一下消息的回收机制

(点击访问,内部是单链表结构)


二.事件分发机制

这个是面试必问的,也是我们必懂的,请大家点击专题访问学习.
(点击访问专题)

三.主线程如何向子线程发送Message消息?

法1:使用IntentService

  • 写一个类继承Intent服务,然后重写onHandleIntent(Intent intent)方法即可,该类中该方法是在子线程中.
  • 启动服务并传过来就是在子线程中获取信息了,然后还可再往当前主线程发消息谈Toast;
    (点击链接访问专题)

法2:通过Handler和Looper发送

  • 既然我们说Hander是主线程和子线程沟通的桥梁,那么Handler肯定有办法也能主传给子.
  • 具体逻辑是(和我们平时的正好相反,并且多加了Looper的3个方法):

    • 子线程:

      • 1.Looper准备
      • 2.新建Hander对象
      • (Looper.myLooper()为的是外部调用后能跳出消息循环)
      • 3.Looper让消息循环
    • onStart开启线程,然后点击1的时候主线程就往里发消息,点击2和销毁的时候跳出消息循环,预防内存泄露

  • 代码如下:

public class MainActivity2 extends Activity {
    private Handler mMySubHandler;
    private Looper  myLooper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
    }

    @Override
    protected void onStart() {
        super.onStart();
        /**
         *  当Activity启动的时候创建一个子线程,并启动
         */
        MyThread myThread = new MyThread();
        myThread.start();
    }

    /**
     * 绑定布局中的点击按钮,点击后给子线程发送消息
     * @param view
     */
    public void click(View view) {
        Message msg = new Message();
        msg.obj = "MainActivity";
        mMySubHandler.sendMessage(msg);
    }

    /**
     * 按钮2,关闭子线程,让子线程退出
     * 即让子线程的Looper对象退出即可,因为Looper.loop();是"线程阻塞"
     */
    public void click2(View view) {
        if (myLooper != null) {//不是空证明还有,但要退出了
            myLooper.quit();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //退出的时候也要释放,不然可能内存泄露
        if (myLooper != null) {
            myLooper.quit();
        }
    }
    //子线程
    class MyThread extends Thread {
        @Override
        public void run() {
            //1.创建一个Looper对象
            //(内部创建了MessageQueue,并将MessageQueue作为Looper对象的成员,然后将Looper对象绑定到ThreadLocal中,Handler思维)
            Looper.prepare();
            //创建Handler
            mMySubHandler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    //处理主线程发送的消息
                    System.out.println("接收到主线程发来的消息 : " + msg.obj);
                }
            };
            //2.获取当前的Looper对象,myLooper为的是外部调用后能跳出消息循环
            myLooper = Looper.myLooper();
            //3.让消息循环起来
            Looper.loop();
            System.out.println("子线程退出");
        }
    }
}
  • 运行结果:

点击1时

I/System.out: 接收到主线程发来的消息 : MainActivity

点击2时:

I/System.out: 子线程退出
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值