说明:
本文不是讲怎么通过Handler机制来进行UI的更新,而是绕过Android更新UI的线程判断机制,来进行UI更新的。
正文:
Android要求我们在主线程更新UI,如果在非主线程更新UI,就出出现如下异常:

 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.                                                                             at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6462)

进入ViewRootImpl.checkThead()源码:

  void checkThread() {        if (mThread != Thread.currentThread()) {            throw new CalledFromWrongThreadException(                    "Only the original thread that created a view hierarchy can touch its views.");        }    }

Android UI更新的时候在这里进行的线程判断,如果不是主线程,就不能更新UI,即抛出异常CalledFromWrongThreadException所以我们只要在其他线程里把这个异常给捕获了,就可以在别的线程里更新UI了。代码如下:

 class Test implements Runnable {        private TextView textView;        public Test(TextView textView) {            this.textView = textView;        }        @Override        public void run() {            try {                textView.setText("new thread set textview");            } catch (RuntimeException e) {                e.printStackTrace();            }          }    }

当然这种方式违法了Android官方本意,也没有什么技术含量。我为什么会想到这种方式呢?还是因为看了何红辉的《Android源码设计模式解析与实践》一书中的一个Demo产生了疑问。
大致代码如下(加入了我的一部分调试代码):

public class ImageLoader {    private static final String TAG = "ImageLoader";    LruCache mImageCache;    ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());    public Thread mThread;    public ImageLoader() {        initImageCache();    }    private void initImageCache() {        final int maxMermory = (int) (Runtime.getRuntime().maxMemory() / 1024);        final int cacheSize = maxMermory / 4;        mImageCache = new LruCache(cacheSize) {            @Override            protected int sizeOf(String url, Bitmap bitmap) {                return bitmap.getRowBytes() * bitmap.getHeight() / 1024;            }        };    }    public void displayImage(final String url, final ImageView imageView, final TextView textView) {        imageView.setTag(url);        mExecutorService.submit(new Runnable() {            @Override            public void run() {                Bitmap bitmap = downloadImage(url);                if (bitmap == null) {                    Log.e(TAG, "bitmap is null!!!!");                    return;                }                if (imageView.getTag().equals(url)) {                    textView.setText("线程池中的数据");//                    if (Looper.myLooper() == Looper.getMainLooper())                    imageView.setImageBitmap(bitmap);//                    if (mThread == Thread.currentThread()) {////                    } else {                        System.out.println("啦啦啦啦德玛西");                        throw new IllegalArgumentException("你必须在主线程调用该方法");//                    }                 }                bitmap.recycle();                mImageCache.put(url, bitmap);            }        });    }    public Bitmap downloadImage(String imageUrl) {        Bitmap bitmap = null;        try {            URL url = new URL(imageUrl);            final URLConnection conn = url.openConnection();//            final HttpURLConnection conn = (HttpURLConnection) url.openConnection();            conn.connect();            bitmap = BitmapFactory.decodeStream(conn.getInputStream());        } catch (MalformedURLException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }        return bitmap;    }}

我发现一个问题:在线程池中竟然可以更新UI,而我又试了在普通的线程了确不行,并且在线程池中的run()方法里,竟然无法抛出异常。所以我又试了如下代码:

public class TestExecutor {    public static void main(String[] args) {        ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());        mExecutorService.submit(new Runnable() {            @Override            public void run() {                throw new IllegalStateException("啦啦啦啦德玛西亚");            }        });    }}

这里边的异常也如法抛出。于是看了看源码,上网查看了线程池的使用,发现在线程池自动捕获了我们在run()方法里抛出的异常,所以程序能够正常执行。
具体请参考,Java线程池异常处理最佳实践
说到底还是涉及到了Java线程池的使用问题,希望通过这个例子加深大家对Java线程池的理解。

更多相关文章

  1. 移动网站开发中常用的10段JavaScript代码
  2. Android Studio制作简易计算器源代码及详解
  3. Android 代码实现logcat输出到文件
  4. Java(Android)线程池
  5. Android代码中运行shell命令
  6. android中 代码实现截图功能(静态+动态视频)
  7. Android获取cpu和内存信息、网址的代码
  8. Android Studio 配置SVN 及 代码管理

随机推荐

  1. Android(安卓)SDK 安装过程 与 安装失败
  2. Android(安卓)Property Animation动画
  3. Android电源管理简介(下)
  4. Android(安卓)Camera 五 Camera HAL v1
  5. Android(安卓)Design Support Library概
  6. Android(安卓)aapt 资源打包工具
  7. 2011.09.26(3)——— android sample之Note
  8. android 知识点
  9. Android在启动adb时失败解决方案?
  10. android如何判断服务是否正在运行状态