我们都知道android中,不允许在子线程中更新UI,凡是更新UI的操作必须放到主线程中,否则就会报如下异常:

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

既然如此,android肯定也会给我们解决办法。

第一种:利用handler

1)private Handler handler = new Handler(){        public void handleMessage(android.os.Message msg){            
//这里是主线程 在这更新UI }; };
// 往handler发送一条消息 更改button的text属性 Message message = handler.obtainMessage();//当然也可以直接new 但是不推荐 因为通过obtainMessage实际是从消息池中获取的,可以节省内存
message.what = 1 ; handler.sendMessage(message); 2)或者是通过handler的post方法回到主线程
handler.post(new Runnable() {    @Override    public void run() {            }});

在这有一点需要注意 在非UI线程中使用handler时,需要
Looper.prepare(); // 创建该线程的Looper对象 handler = new Handler(Looper.myLooper()) { public void handleMessage(android.os.Message msg) { Log.i( "handleMessage" , "" + msg.what); }; }; Looper.loop(); 第二种:利用异步任务
package com.personal.xiaoshuai.demo;import android.content.Context;import android.graphics.Bitmap;import android.os.AsyncTask;import android.widget.Toast;class MyAsyncTask extends AsyncTask<String, Integer, Bitmap> {    private Context context;    public MyAsyncTask(Context context) {        this.context = context;    }    /**     * 运行在UI线程中,在调用doInBackground()之前执行     */    @Override    protected void onPreExecute() {        Toast.makeText(context, "onPreExecute", Toast.LENGTH_SHORT).show();    }    /**     * 后台运行的方法,可以运行非UI线程,可以执行耗时的方法     */    @Override    protected Bitmap doInBackground(String... params) {        return null;    }    /**     * 运行在ui线程中,在doInBackground()执行完毕后执行     */    @Override    protected void onPostExecute(Bitmap bitmap) {        //在这更新UI    }    /**     * 在publishProgress()被调用以后执行,publishProgress()用于更新进度     */    @Override    protected void onProgressUpdate(Integer... values) {        super.onProgressUpdate(values);    }}  第三种:利用runOnUiThread方法中更新UI
//这个方法是activity的方法 假如当前线程是UI线程会立即执行方法体中的方法,如果当前线程不是UI线程,操作是发布到事件队列的UI线程再执行
runOnUiThread(new Runnable() {            @Override            public void run() {              //在这更新UI            }        });
顺便给大家看一下acitivity中的源码,其实它内部也是封装的handler
/** * Runs the specified action on the UI thread. If the current thread is the UI * thread, then the action is executed immediately. If the current thread is * not the UI thread, the action is posted to the event queue of the UI thread. * * @param action the action to run on the UI thread */public final void runOnUiThread(Runnable action) {    if (Thread.currentThread() != mUiThread) {        mHandler.post(action);    } else {        action.run();    }}
第四种:View调用post方法实现更新UI
textView.post(new Runnable() {    @Override    public void run() {        textView.setText("嘻嘻嘻");    }});
view的post方法又是如何实现从子线程中回到主线程的呢 我们看一下
/** * <p>Causes the Runnable to be added to the message queue. * The runnable will be run on the user interface thread.</p> * * @param action The Runnable that will be executed. * * @return Returns true if the Runnable was successfully placed in to the *         message queue.  Returns false on failure, usually because the *         looper processing the message queue is exiting. * * @see #postDelayed * @see #removeCallbacks */public boolean post(Runnable action) {    final AttachInfo attachInfo = mAttachInfo;    if (attachInfo != null) {        return attachInfo.mHandler.post(action);    }    // Assume that post will succeed later    ViewRootImpl.getRunQueue().post(action);    return true;}
可以看到当attachInfo != null(Android的窗口系统就是用过AttachInfo来判断View的所属窗口的)的时候还是会回到handler 假如为null还会走到下面的代码 大致我们可以猜到是放到某个执行队列中当中,我大致跟了下
源码,最终还是回到了handler 。另外AsyncTask内部其实也是对handler进行了封装。
好了,其实没有新知识,建议大家看下handler源码 可以更好的理解android机制。

更多相关文章

  1. Android源码下载,利用一个shell脚本
  2. 《Android面试宝典》学习笔记(第四章:对话框、信息提示和菜单)
  3. 2010.10.30———Android(安卓)03
  4. Android主线程里不允许网络操作
  5. Android* 应用性能调试
  6. Android中的Context详解
  7. Android兼容性问题 -- SparseArray.clone()方法异常
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. 【Android】入门案例(一)——简单登录
  2. 了解Android(安卓)Studio jniLibs目录
  3. 详解Android提交数据到服务器的两种方式
  4. 自定义MediaPlayer控制组件
  5. Android(安卓)同时setTag两次保存多种值
  6. Kotlin For Android介绍
  7. 关于 Android(安卓)Drawable Resource学
  8. Android(安卓)进程间通讯之通过Intent+bu
  9. Service通过Broadcast更新UI
  10. Android(安卓)Path类