Android 进阶之 Handler 消息机制

众所周知,在 Android 中,非 UI 线程中是不能更新 UI 的,如果在子线程中做 UI 相关操作,可能会出现程序崩溃。一般的做法是,创建一个 Message 对象,Handler 发送该 message,然后在 Handler 的 handleMessage() 方法中做 UI 相关操作,这样就成功实现了子线程切换到主线程。

概念

  • 主线程:处理与UI相关的事件(如更新、操作等)

  • 子线程:执行耗时操作(如网络请求、数据加载等)

  • Message(消息):需要被传递的消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,最终由Handler处理。

  • MessageQueue(消息队列):用来存放Handler发送过来的消息,内部通过单链表的数据结构(存储特点:先进先出)来维护消息列表,等待Looper的抽取。

  • Handler(处理者):负责Message的发送及处理。通过 Handler.sendMessage() 向消息池发送各种消息事件;通过 Handler.handleMessage() 处理相应的消息事件。

  • Looper(循环器):通过Looper.loop()不断地从MessageQueue中抽取Message,按分发机制将消息分发给目标处理者。

核心类方法介绍:
method

流程

流程图
Handler.sendMessage()发送消息时,会通过MessageQueue.enqueueMessage()向MessageQueue中添加一条消息;
通过Looper.loop()开启循环后,不断轮询调用MessageQueue.next();
调用目标Handler.dispatchMessage()去传递消息,目标Handler收到消息后调用Handler.handlerMessage()处理消息。

特别注意:
线程(Thread)、循环器(Looper)、处理者(Handler)之间的对应关系如下:

  • 1个线程(Thread)只能绑定 1个循环器(Looper),但可以有多个处理者(Handler)

  • 1个循环器(Looper) 可绑定多个处理者(Handler)

  • 1个处理者(Handler) 只能绑定1个1个循环器(Looper)

使用

  1. 使用 Handler.sendMessage()
public class MainActivity extends AppCompatActivity {
    private Button mButton;

    private TextView mTextView;

    // 步骤1:在主线程中 通过匿名内部类 创建Handler类对象
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            // 步骤5:根据不同线程发送过来的消息,执行不同的UI操作
            if (msg.what == 1){
                mTextView.setText("执行了线程的UI操作");
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = findViewById(R.id.textView);
        mButton = findViewById(R.id.button);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        // 步骤2:创建所需的消息对象
                        Message msg = Message.obtain();
                        msg.what = 1; // 消息标识
                        msg.obj = "A"; // 消息内存存放

                        // 步骤3:在工作线程中 通过Handler发送消息到消息队列中
                        mHandler.sendMessage(msg);
                    }
                }.start(); // 步骤4:开启工作线程(同时启动了Handler)

            }
        });
    }
}
  1. 使用 Handler.post()
public class MainActivity extends AppCompatActivity {
    private Button mButton;
    private TextView mTextView;
    private Handler mHandler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = findViewById(R.id.textView);
        mButton = findViewById(R.id.button);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                mTextView.setText("执行了子线程的UI操作");
                            }
                        });
                    }
                }.start(); 
            }
        });
    }
}
发布了225 篇原创文章 · 获赞 64 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/duoduo_11011/article/details/103917160