Android之多线程与异步浅析
一、如何理解同步与异步?
同步:发出动作后,在收到响应前,什么都不能做;
异步:发出动作后,可以去做其他的事情,不用等待响应。
通俗的理解上述两个概念:同步就是我喊你去吃饭,我要一直等到你回应;异步就是我喊你去吃饭,我就去了,不管你是否回应。
二、为何要用多线程?
Android应用程序在启动时,系统会自动的为该程序生成一个UI线程(即我们常说的主线程),更新页面(UI)的操作都必须在UI线程中进行。与此同时,因为只有一个主线程,在程序运行时,添加控件、点击按钮、网络请求、图片加载等都是在主线程中运行,而这些操作会被放在队列中,顺序执行,每次执行一个事件。这时就会出现一个问题,因为顺序执行且每次只执行一个事件,如果某一个事件执行事件过长(耗时操作),则主线程阻塞,界面卡顿(严重的会报ANR),此时对界面进行操作会出现是否停止响应的提示。这种情况严重影响了操作感。
为了解决此问题,在程序中使用了多线程,即在UI线程(主线程)之外,新建线程(因多用来处理耗时操作,又称之为工作线程)。将主线程中的耗时操作,如网络请求、文件下载等放入工作线程中进行,避免了因耗时操作将主线程阻塞而引起的ANR问题。因此,为了防止出现ANR,才要用多线程。
此外,使用多线程,可以实现异步,也可以进行多任务(多线程下载)。
三、如何处理多线程之间的通信?
通过上述对多线程的理解,在多线程开发过程中,我们需要注意:
- 绝对不能在UI线程中进行耗时操作,以防止阻塞UI线程
- 不能在UI线程之外更新UI
由此两点,那我们该如何处理主线程和工作线程之间的通信呢?Android系统为我们提供了两种方式,是Handler机制和AsyncTaskLoader机制。
(一)Handler机制
主要了解四个类:Looper(循环者)、Handler(消息处理)、Message(消息)、MessageQueue(消息队列)
Looper: 在Android中,一个线程可以产生一个Looper对象,由它来管理该线程中的消息队列(MessageQueue)。调用Looper的Loop()方法后,就会进入一个无限循环中,发现MessageQueue中存在一条消息,就会取出来并传递到Handler的handleMessage()方法中。Looper对象用来为一个线程开启一个消息循环,用来操作MessgeQueue。默认情况下,Android中新创建的线程是没有开启消息循环的(主线程除外)。
Handler:主要用于发送和处理消息。发送信息一般使用Handler的sendMessage()方法,发出的消息经过一系列辗转处理后,最终会传递到Handler的handleMessage()方法中。消息处理类(Handler)允许发送和处理Message和Runnable对象到其所在线程的MessageQueue中。它主要有两个作用:
(1)、将Message应用post()方法或sendMessage()方法发送到MessageQueue中,在发送时可以指定延时发送、发送时间等。当MessageQueue循环到该Message时,调用相应的Handler对象的handlerMessage()方法对其进行处理。
(2)、在子线程中与主线程进行通信,也就是在工作线程中与UI线程进行通信。另外,在一个线程中只能有一个Looper和MessageQueue,但是可以有多个Handler,而且这些Handler可以共享一个Looper和MessageQueue。
Message:是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同的线程之间交换数据,如Message的what字段,和arg1,arg2来携带一些整型的数据,使用obj字段携带一个Object对象。消息类(Message)被存放在MessageQueue中,一个MessageQueue中可以包含多个Message对象。每个Message对象可以通过Message.obtain()方法或者Handler.obtainMessage()方法获得。
MessageQueue:它主要用于存放所有通过Handler发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个MessageQueue对象。
private Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
String message = (String) msg.obj;
System.out.println("从子线程中传递过来的消息:"+message);
//对UI进行更新
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(){
@Override
public void run() {
super.run();
Message msg = new Message();
msg.what = 1;
msg.obj = "要发送的消息";
handler.sendMessage(msg);
}
}.start();
}
(二)AsyncTaskLoader机制:
创建一个子类继承 AsyncTaskLoader 并实现一个最重要的方法loadInBackground(),该方法和doInBackground()原理相同。下次再补充了!
本文地址:https://blog.csdn.net/u013970897/article/details/107407876