Android非主线程更新UI
来源:互联网 发布:朗诵录音软件 编辑:程序博客网 时间:2024/05/17 04:24
说明:
本文不是讲怎么通过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<String, Bitmap> 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<String, Bitmap>(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线程池的理解。
阅读全文
0 0
- Android非主线程更新UI
- 在Android中,非主线程不能更新UI
- Android之UI主线程更新问题
- Android只有主线程才能更新UI?
- Android 更新UI 只能在主线程?
- android学习记录(十一)在非主线程实现更新ui------------Handler
- Android 在非主线程中更新UI也能成功原因详解
- Android禁止在非Activity主线程中更新UI的解决办法
- Handler.post()解决非主线程更新UI
- 在非主线程是否可以更新UI
- Handler-接受子线程数据更新UI主线程;非主线程通信--HandlerThread
- Handler-接受子线程数据更新UI主线程;非主线程通信--HandlerThread
- 在主线程更新UI
- iOS主线程更新UI
- iOS 主线程更新UI
- Android 关于非主线程不能操作UI的认识
- Android之非主线程修改UI (一)
- Android显示系统之View与SurfaceView更新屏幕的区别.对于View.则是在UI主线程中更新画面.SurfaceView更新屏幕,是在非UI线程(主线程)中实现SurfaceHolde
- [译文] 如何高效渲染庞大的地形
- 回调函数理解实例解析
- Java基础之数据类型及运算符
- [leetcode: Python]455. Assign Cookies
- oracle创建临时表空间和数据表空间以及删除
- Android非主线程更新UI
- Cornerstone忽略不必要的文件
- Educational Codeforces Round 21-D
- Struts2_Struts2的处理流程与Action的管理方式
- 教你玩转 Java 的临时文件(创建与删除)
- vue2.0之.vue文件之间$router传值
- jvm类加载机制
- android开发中高德地图点聚合自定义聚合点的样式
- Solitaire's Privacy Policy