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

本文详细介绍了Android中多线程的三种创建方式:继承Thread、实现Runnable接口和匿名类创建。接着,深入解析了Android异步消息处理机制,包括Message、Handler、MessageQueue和Looper的角色。最后,讲解了如何使用AsyncTask进行进程切换,包括其四个关键方法的用法,为开发者提供了在子线程与主线程间操作的便利。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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()方法启动它即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值