Android多线程编程(Multithreading)

当我们需要执行一些耗时的操作,比如说发起网络请求,考虑到服务器未必会立刻响应我们地请求,如果不将操作放置到子线程中就会导致主线程的阻塞,使得软件无法正常运行。

线程和主线程

线程是个单一执行序列,单个线程中的代码会逐步执行。所有Android应用的运行都是从主线程开始的。然而,主线程不是线程那样的预定执行序列,它处于一个无限循环的运行状态,等着用户或系触发事件。一旦有事件触发,主线程便执行代码作出响应。
主线程运行着所有更新UI的代码,其中包括响应activity的启动、按钮点击等不同UI相关事件的代码。由于响应的事件基本都与用户界面相关,主线程也叫UI线程

thread

Thread in Java

In java, a thread is represented by an object belonging to the subclass of java.lang.Thread and overrides its run() method, or a class that implements the Runnable interface, which has one method run().

The thread is created by instantiating the class Thread or the subclass of Thread. When the start() method of a thread object is invoked, it starts the concurrent execution of the thread along with the execution of its parent thread.

For example:

1
new Thread(runnable).start();

### 子线程与主线程通讯机制 因为Android的UI是线程不安全的,所以Android的UI默认是在主线程里面更新。 那当我们子线程获取到数据后需要更新UI怎么办呢,子线程是不能操作UI的,会报错,这个时候子线程要做的就是通知主线程操作UI。 Android中的异步消息处理机制主要由四个部分构成:Message、Handler、MessageQueue和Looper。
#### Message(消息) Message是在线程之间传递的消息,它可以在内部携带少量的信息。 Message对象实例用五个变量可以自定义: - what ( int ) : 用户定义的int型消息代码,用来描述消息 - obj ( Object ) : 用户指定,随消息发送的对象 - target ( Handler ) : 处理消息的Handler - arg1 & arg2 ( int ) : 携带其他整型数据

Handler(消息处理)

Handler不仅仅是处理Message的target(目标),也是创建和发布Message的接口。
handler

MessageQueue(线程使用的收件箱)

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

Looper(消息循环)

Looper是每个线程中的MessageQueue的管家。调用Looper的loop()方法后,就会进入到一个无限循环当中,然后每当发现MessageQueue中存在一条消息,就会将它取出,并传递到Handler的handerMessage()方法中。每个线程只有一个Looper对象。
Looper拥有Message对象的收件箱,所以Message必须在Looper上发布和处理。既然有这层关系,为了协同工作,Handler总引用着Looper,一个Handler仅与一个Looper相关联。一个Message也仅与一个目标Handler相关联。

Handler的使用

一般来讲,不应手动设置消息的目标Handler。创建信息时,最好调用Handler.obtainMessage(…)方法。传入其他必要消息字段后,该方法会自动设置目标Handler。
(我不知道我为什么抽风要把这个写上,因为一般都不是这么用的)

创建Handler对象

设置了3个int型常量,用来区分不同的事件。然后针对不同的事件来做相应的UI操作。这里主要是对RecyclerView的操作和会话列表数据加载完成后对加载动画的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private static final int DATA_CHANGED = 1;//数据集更新
private static final int DATA_INSERTED = -1;//数据集插入
private static final int SET_DATA = 2;//数据集插入

Handler handler = new Handler(){
@Override
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
switch (msg.what){
case DATA_CHANGED:
chatListAdapter.notifyDataSetChanged();
break;
case DATA_INSERTED:
chatListAdapter.notifyItemInserted(msg.arg1);
chatListRv.scrollToPosition(chatListItems.size()-1);
break;
case SET_DATA:
ChatListDAO.setChatList(chatListItems);
chatListAdapter = new ChatListAdapter(chatListItems);
chatListRv.setAdapter(chatListAdapter);
//refreshData完成后关闭加载动画,并将其隐藏
loadingImg.clearAnimation();
loadingLayout.setVisibility(View.GONE);
break;
}
}
};

#### 向主线程发送消息 子线程执行完后,发送消息到handler,由handler进行相关UI操作。
1
2
3
android.os.Message message = new android.os.Message();
message.what = SET_DATA;
handler.sendMessage(message);
dark
sans