Android在子线程中更新UI的方法汇总(共七种)

Android在子线程中更新UI的方法汇总(共七种)

1、常规写法:new Handler()的handleMessage()和handler.sendMessage(msg)

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

   new Thread(new Runnable() {
            @Override
            public void run() {
                Message msg = Message.obtain();
                msg.what = 1000;
                msg.arg1 = 10;
                handler.sendMessage(msg);
            }
        }).start();

2、handler的另一种用法:

    private Handler.Callback callback = new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            return true;
        }
    };
    
	Handler handler1 = new Handler(callback);
        new Thread(new Runnable() {
            @Override
            public void run() {
                Message msg = Message.obtain();
                msg.what = 1001;
                msg.arg1 = 11;
                handler1.sendMessage(msg);
            }
        }).start();

3、handler.post(runnable)

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };
        new Thread(new Runnable() {
            @Override
            public void run() {
                handler.post(new Runnable() {
                    @Override
                    public void run() {

                    }
                });
            }
        }).start();

4、handler.postDelayed(runnable, milliseconds)

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };
        new Thread(new Runnable() {
            @Override
            public void run() {
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {

                    }
                }, 3000);
            }
        }).start();

5、activity.runOnUiThread(runnable)

        new Thread(new Runnable() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {

                    }
                });
            }
        }).start();

6、view.post(runnable)

        new Thread(new Runnable() {
            @Override
            public void run() {
                button.post(new Runnable() {
                    @Override
                    public void run() {

                    }
                });
            }
        }).start();

7、view.postDelayed(runnable, milliseconds)

        new Thread(new Runnable() {
            @Override
            public void run() {
                button.postDelayed(new Runnable() {
                    @Override
                    public void run() {

                    }
                }, 3000);
            }
        }).start();


1、Handler机制
在子线程中通过下图两种方式将UI更新交给Handle来做。在我看来两种用法其实是一致的,没有什么区别,看个人喜好

a.        b.

2、Handler.Post
handler.post(new Runnable(){

    public void run(){

    ......更新.....

    }

});

3、Looper
通过Looper可将UI更新的代码写在线程中
4、runUiThread
runUiThread(new Runnable()......)

下图为我在fragment中的调用,这里要注意一点就是在fragment中要先判断getActivity()是否为空,因为很有可能存在activity还未获取到就运行UI更新的情况,其实跟调用handler.xxx同理,保证调用对象activity / handler的存在。

但是吧,getActivity()获取不一定会非常的迅速,不要问我为什么会知道这个。。。。

     最近用了一下okhttp,原本以为异步callback里面的onResponse是运行在主线程的,后面发现在onResponse里面放了Toast,半天没有反映,一度以为Toast写错了,把Toast放外面发现可以正常弹出提示的,后来查了下资料,原来okhttp的callback,onResponse其实还是运行在子线程的,那么如果在子线程更新主线程呢。这里提供几种方法。

 //定义handler
 static final int SUCCESS=1;
 static final int FAIL=0;
 Handler handler=new Handler(){
 @Override
 public void handleMessage(Message msg) {
 super.handleMessage(msg);
 switch (msg.what) {
 case SUCCESS:
 Toast.makeText(LoginActivity.this, msg.getData().get("msg").toString(), Toast.LENGTH_SHORT).show();
 break;
 case FAIL:
 Toast.makeText(LoginActivity.this, msg.getData().get("msg").toString(), Toast.LENGTH_SHORT).show();
 break;
 default:
 super.handleMessage(msg);
 }
 }
 };
 
 //方法一:通过handler.sendMessage,更新UI主线程
 private void makeToastByHandlerSendMessage(String msgStr)
 {
 Message msg=new Message();
 msg.what=0;
 Bundle bundle=new Bundle();
 bundle.putString("msg",msgStr);
 msg.setData(bundle);
 handler.sendMessage(msg);
 }
 //方法二:通过handler.post,更新UI主线程
 private void makeToastByHandlerPost(final String msg)
 {
 handler.post(new Runnable() {
 @Override
 public void run() {
 Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
 }
 });
 }
 //方法三:通过handler.post,延迟seconds秒后更新UI主线程
 private void makeToastByHandlerPostDelay(final String msg,int seconds)
 {
 handler.postDelayed(new Runnable() {
 @Override
 public void run() {
 Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
 }
 },seconds*1000);
 }
 //方法四:使用runOnUiThread,更新UI主线程
 private void makeToastByRunOnUiThread(final String msg)
 {
 LoginActivity.this.runOnUiThread(new Runnable() {
 @Override
 public void run() {
 Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
 }
 });
 }
 
 //方法五:通过view.post,更新UI主线程
 private void makeToatByViewPost(View view,final String msg)
 {
 view.post(new Runnable() {
 @Override
 public void run() {
 Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
 }
 });
 }
 
 //方法六:通过AsyncTask,更新UI主线程
 private void makeToastByAysncTask(final String msg)
 {
 AsyncTask asyncTask=new AsyncTask() {
 @Override
 protected Object doInBackground(Object[] params) {
 return null;
 }
 
 @Override
 protected void onPostExecute(Object o) {
 super.onPostExecute(o);
 Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
 }
 
 @Override
 protected void onProgressUpdate(Object[] values) {
 super.onProgressUpdate(values);
 }
 };
 asyncTask.execute();
 }
              调用:
              

//1、Handler.SendMessage
makeToastByHandlerSendMessage(msg);
//2、Handler.Post
makeToastByHandlerPost(msg);
//3、Handler.PostDelay
makeToastByHandlerPostDelay(msg,1);
//4、context.RunOnUiThread
makeToastByRunOnUiThread(msg);
//5、View.Post
makeToatByViewPost(btnLogin,msg);
//6、AysncTask
makeToastByAysncTask(msg);



      其实通过查看源代码,发现非handler的实现方法最终还是通过handler来实现的。

 
 LoginActivity.this.runOnUiThread(new Runnable() {});
 view.post(new Runnable() );
 //以上两个方法最终都调用handler的sendMessageDelayed方法
 public final boolean sendMessageDelayed(Message msg, long delayMillis)