您的位置:首页 > 移动开发 > Android开发

Android多线程及异步消息处理机制详解

2019-03-07 13:08 489 查看

1.线程的基本用法

创建一个线程一般有3种方法:

(1)创建一个类继承自Thread,然后重写父类的run()方法,在方法内编写耗时逻辑,代码如下:

[code]class MyThread extends Thread{
@Override
public void run(){
//具体逻辑代码
}
}

启动线程只需要创建MyThread类的实例,然后调用它的start()方法即可:

[code]new MyThread().start();

(2)通过使用实现Runnable接口的方式来定义一个线程,代码如下:

[code]class MyThread implements Runnable{
@Override
public void run(){
//具体逻辑代码
}
}

启动线程的方法如下:

[code]MyThread myThread = new MyThread();
new Thread(myThread).start();

(3)通过使用匿名类的方式创建线程:

[code]new Thread(new Runnable(){
@Override
public void run(){
//具体逻辑代码
}
}).start();

2.异步消息处理机制

Android中的异步消息处理主要由4个部分组成: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中存在Message消息就将它取出,并且传递到Handler的handleMessage()方法中,每个线程中只有一个Looper对象。

由于Handler是在主线程中创建的,handleMessage()方法也会在主线程中运行,这样,只要在子线程中调用sendMessage()方法,就可以从子线程转到主线程中了。具体例子如下:

[code]public class MainActivity extends AppCompatActivity implements View.OnClickListener{
public static final int UPDATE_TEXT = 1;

private TextView text;

private Handler handler = new Handler(){

public void handleMessage(Message msg){//接收消息
switch(msg.what){
case UPTATE_TEXT:
text.setText("Nice to meet you");//UI操作
break;
default:
break;
}
}
};

...

@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);//发送消息
}
}).start();
break;
default:
break;
}
}
}

3.使用AsyncTask进行进程切换

使用AsyncTask可以更方便的从子线程切换到主线程。AsyncTask是一个抽象类,所以得先创建子类继承它,并且重写4个方法:

(1)onPreExecute():该方法会在后台任务开始执行之前调用,用于进行一些界面上的初始化操作。

(2)doInBackground():该方法中的所有代码都会在子线程中运行,所以应该在这里编写耗时逻辑代码,在这个方法中不可以进行UI操作,如果需要进行UI操作,可以调用publishProgress()方法。

(3)onProgressUpdate():当调用了publishProgress()方法之后,就会调用该方法,在该方法中可以进行UI操作。

(4)onPostExecute():当doInBackground()方法执行完毕并且通过return语句进行返回时,就会调用onPostExecute()方法,在该方法中可以进行一些任务的收尾工作。

一个完整得自定义类代码如下:

[code]class DownloadTask extends AsyncTask<Void,Integer,Boolean>{
@Override
protected void onPreExecute(){
progressDialog.show();//显示一个进度对话框
}

@Override
protected Boolean doInBackground(Void...params){
try{
while(true){//开始下载任务
int downloadPercent = doDownload();
publishProgress(downloadPercent);//调用publishProgress()方法进行UI操作
if(downloadPercent>=100){
break;
}
}
}catch(Exception e){
return false;
}
}

@Override
protected void onProgressUpdate(Integer...values){
progressDialog.setMessage("download"+values[0]+"%");//更新UI操作
}

@Override
protected void onPostExecute(Boolean result){
progressDialog.dismiss();//关闭进度对话框
if(result){
Toast.makeText(context,"download succeeded",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context,"download failed",Toast.LENGTH_SHORT).show();
}
}
}

构造完类之后就可以使用了,使用方法很简单,代码如下:

[code]new Download
4000
Task().execute();

总结:使用AsyncTask的方法就是新建一个类去继承它,并且重写类的4个方法,其中在doInBackground()方法中执行具体的耗时操作,如果需要更新UI就在doInBackground()方法中调用publishProgress()方法,调用该方法之后就会自动调用onProgressUpdate()方法,在这个方法里面进行UI操作。当doInBackground()方法执行完毕之后就会自动调用onPostExecute()方法进行任务的收尾工作。最后创建该类的实例,并调用实例的execute()方法启动它即可。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: