参考:《第一行代码》第9章


Android不允许在子线程中进行UI操作的,而我们有些时候,必须在子线程里去执行一些耗时任务,然后根据任务的执行结果来更新相应的UI控件。

针对这种情况,Android提供了一套异步消息处理机制,可以解决在子线程中进行UI操作的问题


############################################


Andriod 中的异步消息处理主要由四个部分组成,Message、Handler、MessageQueue和Looper.


Message:

Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。

Message的what、arg1和arg2字段可以携带一些整型数据,使用obj字段可以携带一个Object对象


Handler:

Handler顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用Handler的sendMessage()方法,而发出的消息经过一系列地辗转处理后,最终会传递到Handler的handleMessage()方法


MessageQueue:

MessageQueue是消息队列的意思,它主要用于存放所有通过Handler发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个MessageQueue对象


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,整个异步消息处理的核心思想就是如此


#############################################################33


案例:在子线程中更新UI


新建一个AndroidThreadTest项目,然后修改activity_main.xml中的代码:

<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">    <Button        android:id="@+id/change_text"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="Change Text"        />    <TextView        android:id="@+id/text"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:text="Hello World"        android:textSize="20sp"        /></RelativeLayout>

布局文件中定义了两个控件,TextView用于在屏幕的正中央显示一个Hello World字符串,Button用于改变TextView中显示的内容


修改MainActivity:

package com.example.administrator.androidthreadtest;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity implements View.OnClickListener {    private TextView text;    private Button changeText;    public static final int UPDATE_TEXT = 1;    private Handler handler =new Handler() {        public void handleMessage(Message msg) {            switch (msg.what) {                case UPDATE_TEXT:                    //进行UI操作                    text.setText("Nice to meet you");                    break;                default:                    break;            }        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        text = (TextView)findViewById(R.id.text);        changeText = (Button)findViewById(R.id.change_text);        changeText.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.change_text:                new Thread(new Runnable() {                    @Override                    public void run() {                        Message message = new Message();                        message.what = UPDATE_TEXT;                        handler.sendMessage(message); //将Message对象发送出去                    }                }).start();                break;            default:                break;        }    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        // Inflate the menu; this adds items to the action bar if it is present.        getMenuInflater().inflate(R.menu.menu_main, menu);        return true;    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        // Handle action bar item clicks here. The action bar will        // automatically handle clicks on the Home/Up button, so long        // as you specify a parent activity in AndroidManifest.xml.        int id = item.getItemId();        //noinspection SimplifiableIfStatement        if (id == R.id.action_settings) {            return true;        }        return super.onOptionsItemSelected(item);    }}


定义一个整型常量UPDATE_TEXT,用于表示更新TextView动作。然后新增一个Handler对象,并重写父类的handleMessage()方法,在这里对具体的Message进行处理。如果发现Message的what字段的值等于UPDATE_TEXT,就将TextView显示的内容改成Nice to meet you







更多相关文章

  1. PHP 即将来到 Google Android?
  2. Android主线程消息循环
  3. Android异步机制一:使用Thread+Handler实现非UI线程更新UI界面
  4. 《第一行代码--Android》读书笔记之多线程与服务
  5. Android中的多线程之handler
  6. Android内存泄漏查找
  7. Android中EventBus事件总线发送网络请求结果更新UI
  8. android 的线程模型和AsyncTask
  9. Android(安卓)AsyncTask实现异步任务的执行

随机推荐

  1. Android节拍器
  2. Android中对Log日志文件的分析
  3. Android官方技术文档翻译——开发工具的
  4. Android事件分发机制完全解析,带你从源码
  5. Android(安卓)XML�O置屏幕方向(android:sc
  6. Android(安卓)Matrix详解
  7. Android(安卓)NDK初识
  8. 怎么让 Android(安卓)程序一直后台运行,像
  9. Android(安卓)imageView图片按比例缩放
  10. 深入理解Android消息处理系统——Looper