1.线程的基本用法
创建一个线程一般有3种方法:
(1)创建一个类继承自Thread,然后重写父类的run()方法,在方法内编写耗时逻辑,代码如下:
class MyThread extends Thread{
@Override
public void run(){
//具体逻辑代码
}
}
启动线程只需要创建MyThread类的实例,然后调用它的start()方法即可:
new MyThread().start();
(2)通过使用实现Runnable接口的方式来定义一个线程,代码如下:
class MyThread implements Runnable{
@Override
public void run(){
//具体逻辑代码
}
}
启动线程的方法如下:
MyThread myThread = new MyThread();
new Thread(myThread).start();
(3)通过使用匿名类的方式创建线程:
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()方法,就可以从子线程转到主线程中了。具体例子如下:
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()方法,在该方法中可以进行一些任务的收尾工作。
一个完整得自定义类代码如下:
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();
}
}
}
构造完类之后就可以使用了,使用方法很简单,代码如下:
new DownloadTask().execute();
总结:使用AsyncTask的方法就是新建一个类去继承它,并且重写类的4个方法,其中在doInBackground()方法中执行具体的耗时操作,如果需要更新UI就在doInBackground()方法中调用publishProgress()方法,调用该方法之后就会自动调用onProgressUpdate()方法,在这个方法里面进行UI操作。当doInBackground()方法执行完毕之后就会自动调用onPostExecute()方法进行任务的收尾工作。最后创建该类的实例,并调用实例的execute()方法启动它即可。