UI更新——消息处理massage
对于安卓内部消息得处理,实现对界面UI得更新操作,不能在线程中直接更新ui。至于为什么不能,在学习安卓开发的时候,在线程中操作会使程序崩溃。
为什么,可以看看诸多大神们的详细介绍。
安卓内部处理数据更新UI都是耗时的操作,这些耗时操作系统不允许在Activity主线程中进行,必须在其他线程中操作,然后通过发消息的形式通知主线程更新UI,那么我们就要用多线程处理了,massage 消息处理机制。
下面我们一起分享郭霖Android多线程中消息处理更新UI的介绍。
通过一个具体的例子来验证一下吧。新建一个 AndroidThreadTest 项目,然后修改 activity_main.xml 中的代码,如下所示:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" > 4 <Button 5 android:id="@+id/change_text" 6 android:layout_width="match_parent" 7 android:layout_height="wrap_content" 8 android:text="Change Text" /> 9 <TextView 10 android:id="@+id/text" 11 android:layout_width="wrap_content" 12 android:layout_height="wrap_content" 13 android:layout_centerInParent="true" 14 android:text="Hello world" 15 android:textSize="20sp" /> 16 </RelativeLayout>
布局文件中定义了两个控件,TextView 用于在屏幕的正中央显示一个 Hello world 字符串,Button 用于改变 TextView 中显示的内容,我们希望在点击 Button 后可以把 TextView中显示的字符串改成 Nice to meet you。接下来 MainActivity 中的代码,如下所示:
1 public class MainActivity extends Activity implements OnClickListener { 2 public static final int UPDATE_TEXT = 1; 3 private TextView text; 4 private Button changeText; 5 private Handler handler = new Handler() { 6 public void handleMessage(Message msg) { 7 switch (msg.what) { 8 case UPDATE_TEXT: 9 // 在这里可以进行UI 操作 10 text.setText("Nice to meet you"); 11 break; 12 default: 13 break; 14 } 15 } 16 }; 17 …… 18 19 @Override 20 public void onClick(View v) { 21 switch (v.getId()) { 22 case R.id.change_text: 23 new Thread(new Runnable() { 24 @Override 25 public void run() { 26 Message message = new Message(); 27 message.what = UPDATE_TEXT; 28 handler.sendMessage(message); // 将Message 对象发送出去 29 } 30 }).start(); 31 break; 32 default: 33 break; 34 } 35 } 36 }
这里我们先是定义了一个整型常量 UPDATE_TEXT,用于表示更新 TextView这个动作。然后新增一个 Handler 对象,并重写父类的 handleMessage 方法,在这里对具体的 Message进行处理。如果发现 Message 的 what 字段的值等于 UPDATE_TEXT,就将 TextView显示的内容改成 Nice to meet you。下面再来看一下hange Text 按钮的点击事件中的代码。可以看到,这次我们并没有在子线程里直接进行 UI 操作,而是创建了一个 Message(android.os.Message)对象,并将它的 what 字段的值指定为 UPDATE_TEXT,然后调用 Handler 的 sendMessage()方法将这条Message 发送出去。很快,Handler 就会收到这条 Message,并在 handleMessage()方法中对它进行处理。注意此时 handleMessage()方法中的代码就是在主线程当中运行的了,所以我们可以放心地在这里进行 UI 操作。接下来对 Message 携带的 what 字段的值进行判断,如果等于UPDATE_TEXT,就将 TextView显示的内容改成 Nice to meet you。现在重新运行程序,可以看到屏幕的正中央显示着 Hello world。然后点击一下 ChangeText按钮,显示的内容着就被替换成 Nice to meet you,如图:
使用Massage消息机制处理ui线程,简单操作。接下来解析异步消息处理机制的到底是如何工作的。
Android 中的异步消息处理主要由四个部分组成,Message、Handler、MessageQueue和Looper。其中Message和Handler在上一小节中我们已经接触过了,而MessageQueue和Looper对于你来说还是全新的概念,下面我就对这四个部分进行一下简要的介绍。
1. MessageMessage 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。上一小节中我们使用到了 Message 的 what 字段,除此之外还可以使用 arg1 和 arg2 字段来携带一些整型数据,使用 obj字段携带一个 Object 对象。
2. HandlerHandler 顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用 Handler的SendMessage()方法,而发出的消息经过一系列地辗转处理后,最终会传递到 Handler的 handleMessage()方法中。
3. MessageQueueMessageQueue是消息队列的意思,它主要用于存放所有通过 Handler发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个 MessageQueue对象。
4. LooperLooper是每个线程中的 MessageQueue的管家,调用 Looper的 loop()方法后,就会进入到一个无限循环当中,然后每当发现 MessageQueue 中存在一条消息,就会将它取出,并传递到 Handler 的 handleMessage()方法中。每个线程中也只会有一个 Looper对象。
了解了 Message、Handler、MessageQueue 以及 Looper的基本概念后,我们再来对异步消息处理的整个流程梳理一遍。首先需要在主线程当中创建一个 Handler 对象,并重写handleMessage()方法。然后当子线程中需要进行 UI 操作时,就创建一个 Message 对象,并通过 Handler 将这条消息发送出去。之后这条消息会被添加到 MessageQueue 的队列中等待被处理,而 Looper 则会一直尝试从 MessageQueue 中取出待处理消息,最后分发回 Handler的 handleMessage()方法中。由于 Handler是在主线程中创建的,所以此时 HandleMessage()方法中的代码也会在主线程中运行,于是我们在这里就可以安心地进行 UI 操作了。整个异步消息处理机制的流程示意图:
一条 Message 经过这样一个流程的辗转调用后,也就从子线程进入到了主线程,从不能更新 UI 变成了可以更新 UI,整个异步消息处理的核心思想也就是如此。
下面分享自己的所学所做关于安卓中的一些消息处理,信息的传递。bundle传递object对象。