zoukankan      html  css  js  c++  java
  • 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方法处理消息。

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

  • 相关阅读:
    ZRender实现粒子网格动画实战
    线段树专题—ZOJ1610 Count the Colors
    LeetCode Recover Binary Search Tree
    Android跨进程訪问(AIDL服务)
    刘下记录:ImageView.scaleType 属性全解析(含视频)
    myeclipse解决JSP文件里script背景颜色的调整
    hdu 5381 The sum of gcd(线段树+gcd)
    newlisp HTTP Basic Authentication
    codeforces 132C Logo Turtle--- dp dfs
    python代码风格-PEP8
  • 原文地址:https://www.cnblogs.com/dearnotes/p/12189643.html
Copyright © 2011-2022 走看看