Android 异步消息处理机制

本篇讲解android子线程中更新UI的三种方法。

1. Handler

public class TestHandlerFragment extends BaseFragment implements View.OnClickListener {

private Button button;

private Handler mhandler = new Handler() {
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case ST_HANDLER_LICENSE_GET:
                button.setText("after change Btn Text");
                break;
           default:
        }
    }
};
private void changeBtnText() {
//当触发changeBtnText,会执行子线程方法,执行结束发送handler去主线程。

  doSubThreadAction();

  mhandler.sendEmptyMessageDelayed(ST_HANDLER_LICENSE_GET, 100);
}
}

 

组成部分:Message, Handler, MessageQueue, Looper

流程:

(1)主线程中创建handler对象,并重写handleMessage()方法。

(2)子线程更新UI,创建一个Message对象,通过handler将消息发送出去。之后这条消息会被添加到MessageQueue中等待被处理。而Looper则会一直尝试从MessageQueue中取出待处理消息,最后分发回handler里的handleMessage()方法中。

(3)因为handler是在主线程中创建,所以handleMessage()也是在主线程中执行。

2. runOnUiThread(),实现原理同上handler流程。是异步消息处理的接口封装。

(1)activity_main

.xml

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/runOnUIThread_btn"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:text="First Button"
        />

</android.support.constraint.ConstraintLayout>
(2)MainActivity.java
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate: ");

    }

    @Override
    protected void onResume() {
        super.onResume();
        final Button button = (Button) findViewById(R.id.runOnUIThread_btn);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
//更新UI button的内容
                button.setText("RunOnUIThread-Button");
            }
        });

    }
}

3. AsyncTask

/**
* AsyncTask是个抽象类,需要子类继承它。
* AsyncTask第一个参数:需要传递参数到后台任务,void表示不需要
* AsyncTask第二个参数:表示用整型数据表示进度显示单位
* AsyncTask第三个参数:便是返回值的类型
*/
public class DownloadTask extends AsyncTask<Void, Integer, Boolean> {

    private ProgressDialog progressDialog;

    private Context context;

    public DownloadTask(ProgressDialog progressDialog, Context context){
        this.progressDialog = progressDialog;
        this.context = context;
    }

    @Override
    protected void onPreExecute() {
        //该方法在后台任务开始执行前调用,用于一些界面上的操作,这里是弹出进度条。
        progressDialog.show();
    }

    @Override
    protected Boolean doInBackground(Void... voids) {
        //该方法执行耗时操作,在子线程中执行,不能更新UI。
        while (true) {
            int downloadPercent = doDownload();
            //如果想更新UI,调用publishProgress方法,它会自动去调用onProgressUpdate方法。
            publishProgress(downloadPercent);
            if(downloadPercent >= 100){
                break;
            }
        }

        return true;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        progressDialog.setMessage("Download "+values[0] + "%");
    }

    @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();
        }
    }

    private int doDownload() {
        //执行具体的download操作,在此为了方便返回一个常量值。
        return 1;
    }
}

 




作者:Susie 
出处:https://www.cnblogs.com/zwting/p/9909466.html  
欢迎转载,但还请尊重劳动果实,保留此段声明并注明原文链接。

 

posted @ 2018-11-05 15:40  我是个神经病  阅读(219)  评论(0编辑  收藏  举报