Android通過子線程更新UI的幾種方式


一般情況下,UI的更新都少不了Handler,首先我們先了解一下Handler機制:

Handler消息機制

定義
Message
線程間通信的數據單元,可通過message攜帶需要的數據創建對象:Message.obtain(what)

Handler
Handler是Message的處理器,同時也負責消息的發送和移除工作
發送即時消息:即使發送即時處理
發送延時消息:即時發送,過一會兒處理

MessageQueue:消息隊列
用來存放通過Handler發送的消息,它是一個按Message的when排序的優先級隊列

Looper:循環器
負責循環取出Message Queue里面的當前需要處理的Message,交給對應的Handler進行處理,處理完后,將Message緩存到消息池中,以備復用

Handler的基本使用
步驟:
①創建Handler成員變量,並重寫其handleMessage()
②在分線程創建Message對象
③使用handler對象發送Message
④在handleMessage()中處理消息

消息機制原理

文字描述
從handler中獲取一個消息對象,把數據封裝到消息對象中,通過handler的send方法把消息push到MessageQueue隊列中,looper對象會輪詢MessageQueue隊列,把消息對象取出。通過dispatchMessage分發給Handler,再回調用Handler實現的handleMessage方法處理消息。

這里只是大致地描述了Handler消息機制的流程,你也可以跟着這位的文章讀下源碼https://blog.csdn.net/yanzhenjie1003/article/details/89218745

接下來,我們再看在通過子線程更新UI常見的幾種方式

通過子線程更新UI

首先我們要理解子線程可不可以更新UI,谷歌官方的說法是:一定要在主線程更新UI。

這是為什么?
如果多個線程更新UI,很容易造成整個界面的UI出錯。

那為什么又有通過子線程更新UI這種說法呢?
當我們需要進行耗時操作時(如聯網等),如果放在主線程,會對整個應用造成極大的負擔,用戶體驗極差,所以我們就通過Handler機制新開辟一個線程,耗時操作交給子線程,UI的更新實際還是主線程來實現的。
所以嚴謹來說是通過子線程更新UI,而不是子線程更新UI。

通過子線程更新UI

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button update_handler;
    private Button update_ViewPost;
    private Button update_handlerPost;
    private Button update_handlerPostDelay;
    private Button update_RunOnUiThread;
    private Button update_AsyncTask;
    private TextView textView;




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        update_handler=findViewById(R.id.button1);
        update_ViewPost=findViewById(R.id.button2);
        update_handlerPost=findViewById(R.id.button3);
        update_handlerPostDelay=findViewById(R.id.button4);
        update_RunOnUiThread=findViewById(R.id.button5);
        update_AsyncTask=findViewById(R.id.button6);
        textView=findViewById(R.id.myword);

        update_handler.setOnClickListener(this);
        update_ViewPost.setOnClickListener(this);
        update_handlerPost.setOnClickListener(this);
        update_handlerPostDelay.setOnClickListener(this);
        update_RunOnUiThread.setOnClickListener(this);
       update_AsyncTask.setOnClickListener(this);

    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button1:
                update_handler();

                break;
            case R.id.button2:
                update_ViewPost();
                break;
            case R.id.button3:
                update_handlerPost();
                break;
            case R.id.button4:
                update_handlerPostDelay();
                break;
            case R.id.button5:
                update_RunOnUiThread();
                break;
            case R.id.button6:
                new updateAsyncTask().execute();
                break;
        }

    }



    Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.what==1){
                textView.setText("小慕慕");
            }
        }
    };
/*
方法1
 */
    private void update_handler(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                Message message=handler.obtainMessage();
                message.what=1;
                handler.sendMessage(message);

            }
        }).start();

    }
    /*
    方法2
     */
    private void update_ViewPost(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                textView.post(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("小九九");
                    }
                });


            }
        }).start();
    }
    /*
    方法3
     */

    private void update_handlerPost() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("小酒酒");
                    }
                });
            }
        }).start();
    }
/*
方法4
 */
    private void update_handlerPostDelay(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("九酒");
                    }
                },3000);
            }
        }).start();
    }
/*
方法5
 */
    private void update_RunOnUiThread(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("慕九");
                    }
                });

            }
        }).start();
    }
/*
方法6
 */
    class  updateAsyncTask extends AsyncTask<String,Integer,String>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected String doInBackground(String... strings) {

            publishProgress();
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            textView.setText("結束");
        }
    }

}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity"
    >


    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="handler"
        android:textAllCaps="false"
        />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="View.post()"
        android:textAllCaps="false"
       />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="handlerPost()"
        android:textAllCaps="false"/>

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:layout_gravity="center_horizontal"
        android:text="handlerPostDelay()"
        android:textAllCaps="false"/>
    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:layout_gravity="center_horizontal"
        android:text="runOnUiThread()"
        android:textAllCaps="false"/>

    <Button
        android:id="@+id/button6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:layout_gravity="center_horizontal"
        android:text=" update_AsyncTask()"
        android:textAllCaps="false"/>

    <TextView
        android:id="@+id/myword"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="慕九酒"/>

</LinearLayout>

運行結果:

總結
其實這六種方式並沒有太大的區別,前五種方式都是基於第一種方式的封裝,都是采用的Thread+handler模式,第六種封裝的更厲害了些,它是Thread+hanler+Threadpool。上面的代碼示例中有些看起來完全是在子線程更新的UI,實際上這是因為做的封裝讓我們看着好像是在子線程更新UI似的,實際上如果我們查看源碼,就會發現它還是通過handler機制在主線程更新的UI.

參考https://blog.csdn.net/oheg2010/article/details/93092541


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM