更新AndroidUI线程的方法

参考

Processes and Threads

重点

  1. Do not block the UI thread
  2. Do not access the Android UI toolkit from outside the UI thread

这样写是不对的

        findViewById(R.id.demo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Bitmap b = loadImageFromNetwork("http://www.baidu.com/img/bdlogo.png");
                        mImageView.setImageBitmap(b);
                    }
                }).start();
            }
        });

do not access the Android UI toolkit from outside the UI thread—this sample modifies the ImageView from the worker thread instead of the UI thread. This can result in undefined and unexpected behavior, which can be difficult and time-consuming to track down.

可以改成这样的

Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help:

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable, long)
        findViewById(R.id.demo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        final Bitmap bitmap = loadImageFromNetwork(http://www.baidu.com/img/bdlogo.png);
                        MainActivity.this.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                mImageView.setImageBitmap(bitmap);
                            }
                        });
                    }
                }).start();
            }
        });

我们看一下 runOnUiThread 的源码:

    public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

会发现此方法首先判断当前线程是不是 UI线程,不是的话使用 Handler 的 post 方法,是的话直接调用 run 方法。

我们接着看 View.post(Runnable) 的写法:

        findViewById(R.id.demo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        final Bitmap bitmap = loadImageFromNetwork(http://www.baidu.com/img/bdlogo.png);
                        mImageView.post(new Runnable() {
                            @Override
                            public void run() {
                                mImageView.setImageBitmap(bitmap);
                            }
                        });
                    }
                }).start();
            }
        });

通过查看 View.post(Runnable) 的源码:

    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;
    }

能够发现它其实也调用了 Handler 的 post 方法。View.postDelayed(Runnable, long) 就比 View.post(Runnable) 多了个时间参数,很好理解,不做赘述。

综上可知,前面提到的三种方法其实都是对 Handle + Message 的包装。

用 AsyncTask 更新 UI

Android 那帮人真是为开发者着想啊,AsyncTask 真是太好用了。同时,需要注意以下几点:

  • AsyncTask 必须声明在 UI 线程上。
  • AsyncTask 必须在 UI 线程上实例化。
  • 必须通过 execute() 方法执行任务。
  • 不可以直接调用 onPreExecute()、onPostExecute(Resut)、doInBackground(Params...)、onProgressUpdate(Progress...) 方法。

你可能感兴趣的:(更新AndroidUI线程的方法)