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()中处理消息

消息机制原理

Android通过子线程更新UI的几种方式_第1张图片

文字描述
从handler中获取一个消息对象,把数据封装到消息对象中,通过handler的send方法把消息push到MessageQueue队列中,looper对象会轮询MessageQueue队列,把消息对象取出。通过dispatchMessage分发给Handler,再回调用Handler实现的handleMessage方法处理消息。

接下来,我们再看在通过子线程更新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{

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

}

布局文件





    

运行结果:

Android通过子线程更新UI的几种方式_第2张图片

总结
其实这六种方式并没有太大的区别,前五种方式都是基于第一种方式的封装,都是采用的Thread+handler模式,第六种封装的更厉害了些,它是Thread+hanler+Threadpool。上面的代码示例中有些看起来完全是在子线程更新的UI,实际上这是因为做的封装让我们看着好像是在子线程更新UI似的,实际上如果我们查看源码,就会发现它还是通过handler机制在主线程更新的UI.

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

你可能感兴趣的:(Android通过子线程更新UI的几种方式)