Android学习笔记---Handler机制

先了解下Android中主线程与子线程的概念:
在一个Android 程序开始运行的时候,会单独启动一个Process(进程)。默认的情况下,所有这个程序中的Activity或者Service都会跑在这个Process,一个Android 程序默认情况下也只有一个Process,但一个Process下却可以有许多个Thread(线程)。
在这么多Thread当中,有一个Thread,我们称之为主线程,也就是UI Thread。UI Thread在Android程序运行的时候就被创建,是一个Process当中的主线程Main Thread,主要是负责控制UI界面的显示、更新和控件交互,Android的UI线程不安全的,也就是说,如果想要更 新应用程序里的 UI 元素,则必须在主线程中进行,否则就会出现异常。

下面以一个具体的例子来说明下在子线程中更新UI:
布局文件如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">

    <TextView  android:id="@+id/tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Hello Android" android:textSize="25sp" android:gravity="center"/>
    <Button android:id="@+id/bt" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="更换TextView内容"/>

</LinearLayout>

MainActivity代码如下:

package com.example.androidstudyhandler;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
    private Button button;
    private TextView textview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.bt);
        textview = (TextView) findViewById(R.id.tv);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        textview.setText("Android Hello");
                    }
                }).start();
            }
        });
    }
}

运行点击按钮后程序会崩溃,Logcat报错如下:

但是有些时候,我们必 须在子线程里去执行一些耗时任务(访问网络,下载数据,查询数据库等), 然后根据任务的执行结果来更新相应的 UI 控件, 对于这种情况下我们就需要用到Android提供的Handler异步消息处理机制来进行更新了。
改一下MainActivity中的代码如下:

package com.example.androidstudyhandler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
    private Button button;
    private TextView textview;
    private static final int UPDATE_TEXT = 1;

    private Handler handler = new Handler(){
        public void handleMessage(Message msg){
            switch(msg.what){
            case UPDATE_TEXT:
                textview.setText("I Love Android");
                break;
            default:
                break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.bt);
        textview = (TextView) findViewById(R.id.tv);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message message = new Message();
                        message.what = UPDATE_TEXT;
                        handler.sendMessage(message);
                    }
                }).start();
            }
        });
    }
}

再点击按钮就可以成功更新TextView了:
Android学习笔记---Handler机制_第1张图片

在上面通过Handler更新UI过程中我们接触到了Message类,Handler类,其实Android中的异步消息处理主要由四个部分组成Message、Handler、MessageQueue 和 Looper。
1. Message
Message 是在线程之间传递的消息, 它可以在内部携带少量的信息, 用于在不同线程之间交换数据。
2. Handler
Handler 顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用 Handler 的 sendMessage()方法,而发出的消息经过一系列地辗转处理后, 最终会传递到 Handler 的 handleMessage()方法中。
3. MessageQueue
MessageQueue 是消息队列的意思, 它主要用于存放所有通过 Handler 发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个MessageQueue 对象。
4. Looper
Looper 是每个线程中的 MessageQueue 的管家,调用 Looper 的 loop()方法后,就会 进入到一个无限循环当中,然后每当发现 MessageQueue中存在一条消息,就会将它取出,并传递到 Handler 的 handleMessage()方法中。每个线程中也只会有一个 Looper 对象。

所以异步消息处理的整个流程是首先需要在主线程当中创建一个 Handler 对象, 并重写 handleMessage()方法。然后当子线程中需要进行 UI 操作时, 就创建一个 Message 对象,并通过 Handler 将这条消息发送出去。之后这条消息会被添加到 MessageQueue 的队列中等待被处理, 而 Looper 则会一直尝试从 MessageQueue 中取出待处理消息, 最后分发回Handler 的handleMessage()方法中。由于 Handler 是在主线程中创建的, 所以此时 handleMessage()方法中的代码也会在主线程中运行,于是我们在这里就可以安心地进行 UI 操作了。
一条 Message 经过这样一个流程的辗转调用后, 也就从子线程进入到了主线程,从不能 更新 UI 变成了可以更新 UI,整个异步消息处理的核心思想也就是如此。

你可能感兴趣的:(Android学习笔记---Handler机制)