Android多线程编程

    当我们需要执行一些耗时操作,如果不将这类操作放在子线程里去运行,就会导致主线程被阻塞住,从而影响用户对软件的正常使用。

1.线程的基本用法

    定义一个线程只需要新建一个类继承自Thread,然后重写父类的run()方法,并在里面编写耗时逻辑即可。只要new出该类的实例,然后调用它的start()方法,这样run()方法中的代码就会在子线程中运行了。

class MyThread extends Thread{
        @Override
        public void run() {
            //具体处理逻辑
        }
    }
    
    new MyThread().start();


这种方式耦合性有点高,更多的时候我们选择使用实现Runnable接口的方式来定义一个线程。

class MyThread implements Runnable{
        @Override
        public void run() {
            //具体处理逻辑
        }
    }

    MyThread myThread=new MyThread();
    new Thread(MyThread).start();

如果你不想再定义一个类,也可以使用匿名类的方式,这种方式更常见

new Thread (new Runnable()){

        @Override
        public void run() {
            //具体处理逻辑
        }

    }).start();

2.在子线程中更新UI

    Android的UI是线程不安全的,如果想更新应用程序的UI元素,则必须在主线程中进行。我们可以创建一个例子来证明。首先在按钮的点击事件里开启一个子线程,然后在子线程里将TextView显示的内容进行更换,结果发现点击按钮后程序崩溃。

    但是有时候,我们必须在子线程里去执行一些耗时任务,然后根据任务的执行结果来更新相应的UI控件,这该如何是好呢?其实,安卓提供了一套异步消息处理机制,完美解决了这个问题。我们继续上面那个例子,只不过这次我们在里面加入异步消息机制。

public class MainActivity extends AppCompatActivity {
    public static final int UPDATE_TEXT=1;
    private TextView textView;

    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what){
                case UPDATE_TEXT:
                    textView.setText("Nice to see you!");
                    break;
                default:
                    break;
            }
        }
    } ;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView=(TextView)findViewById(R.id.text_view);
        Button button=(Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message message=new Message();
                        message.what=UPDATE_TEXT;
                        handler.sendMessage(message);
                    }
                }).start();
            }
        });
    }
}

3.解析异步消息机制

    异步消息处理主要由4部分组成:Message、Handler、MessageQueue和Looper。

(1)Message

    是在线程间传递的消息,可以在内部携带少量信息。

(2)Handler

    用于发送和处理消息。

(3)MessageQueue

    存放所有通过Handler发送的消息。每个线程只能有一个MessageQueue对象。

(4)Looper

    取出MessageQueue中的消息,并将它传递到Handler的handleMessage()方法中。

4.使用AsyncTask

    借助AsyncTask,即使不了解异步消息处理机制也可以简单地从子线程切换到主线程。

    AsyncTask的基本用法,创建一个子类去继承它,继承时为AsyncTask类指定三个泛型参数。Params:在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。Progress:后台任务执行时,如果需要在界面上显示当前进度,则使用这里指定的泛型作为进度单位。Result:当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。

    然后,我们还要重写AsyncTask的方法,有4个:

(1)onPreExecute()

    这个方法会在后台任务执行之前调用,用于界面上的初始化操作,比如显示一条进度条对话框。

(2)doInBackground(Params...)

    所有的耗时任务应该放在这里,这个方法里的代码会在子线程中运行。任务一旦完成,使用return返回任务的执行结果。注意这里不能进行UI操作,如果需要,比如反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。

(3)onProgressUpdate(Progress...)

   当后台任务调用了publishProgress(Progress...)方法后,onProgressUpdate(Progress...)方法很快就会被调用,该方法的参数就是在后台任务中传递来的,在这里可以通过传入的参数进行UI操作。

(4)onPostExecute(Result)

    后台任务执行完毕并通过return语句返回时,这个方法很快会被调用。返回的数据会作为参数传递到此方法,可以利用这些数据进行UI操作。比如提醒任务执行结果,关闭进度条对话框等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值