在非UI线程里访问 Android UI toolkit—这个在一个worker线程修改了 View 。这会导致不可预期的结果,而且还难以调试。

为了修复这个问题,Android提供了几个方法从非UI线程访问Android UI toolkit 。详见下面的这个列表:

可以使用 View.post(Runnable) 方法来修改之前的代码:

public void onClick(View v){
    new Thread(new Runnable(){
        public void run(){
            final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
            mImageView.post(new Runnable(){
                public void run(){
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();}

  

现在这个方案的线程安全的:这个网络操作在独立线程中完成后,UI线程便会对ImageView 进行操作。

使用 AsyncTask

AsyncTask 能让你在UI上进行异步操作。它在一个worker线程里进行一些阻塞操作然后把结果交给UI主线程,在这个过程中不需要你对线程或者handler进行处理。

使用它,你必须继承 AsyncTask 并实现 doInBackground() 回调方法,这个方法运行在一个后台线程池里面。如果你需要更新UI,那么你应该实现onPostExecute()这个方法从 doInBackground() 取出结果,然后在 UI 线程里面运行,所以你可以安全的更新你的UI。你可以通过在UI线程调用 execute()方法来运行这个任务。

比如,你可以通过使用 AsyncTask来实现之前的例子:

public void onClick(View v){
    new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask<String,Void,Bitmap>{
    /** The system calls this to perform work in a worker thread and
      * delivers it the parameters given to AsyncTask.execute() */
    protected Bitmap doInBackground(String... urls){
        return loadImageFromNetwork(urls[0]);
    }
   
    /** The system calls this to perform work in the UI thread and delivers
      * the result from doInBackground() */
    protected void onPostExecute(Bitmap result){
        mImageView.setImageBitmap(result);
    }}

  

现在UI是安全的了,代码也更加简单了,因为AsyncTask把worker线程里做的事和UI线程里要做的事分开了。

你应该阅读一下 AsyncTask 的参考文档以便更好的使用它。下面就是一个对 AsyncTask 如何作用的快速的总览:

注意: 你在使用worker线程的时候可能会碰到的另一个问题就是因为runtime configuration change (比如用户改变了屏幕的方向)导致你的activity不可预期的重启,这可能会kill掉你的worker线程。为了解决这个问题你可以参考 Shelves 这个项目。

线程安全的方法

在某些情况下,你实现的方法可能会被多个线程所调用,因此你必须把它写出线程安全的。

转自:http://greenrobot.me/devpost/android-thread-and-process/

Android 关于操作UI线程的更多相关文章

  1. Android 操作UI线程的一些方法

    我们经常会在后台线程中去做一些耗时的操作,比如去网络取数据.但是当数据取回来,需要显示到页面上的时候,会遇到一些小麻烦,因为我们都知道,android的UI页面是不允许在其他线程直接操作的.下面总结4 ...

  2. android 在非UI线程更新UI仍然成功原因深入剖析

    ”只能在UI主线程中更新View“. 这句话很熟悉吧? 来来,哥们,看一下下面的例子 @Override       protected void onCreate(Bundle savedInsta ...

  3. Android 高级UI设计笔记17:Android在非UI线程中显示Toast

    1. 子线程的Toast怎么显示不出来? 因为Toast在创建的时候会依赖于一个Handler,并且一个Handler是需要有一个Looper才能够创建,而普通的线程是不会自动去创建一个Looper对 ...

  4. Android在非UI线程中更新UI的方法

    1.使用Thread+Handler实现非UI线程更新UI界面 在UI Thread中创建Handler.用sendMessage(message)或者obtainMessage(result, ob ...

  5. Android中进程与线程及如何在子线程中操作UI线程

    1. Android进程 一个应用程序被启动时,系统默认创建执行一个叫做"main"的线程.这个线程也是你的应用与界面工具包(android.widget和android.view ...

  6. Android 实战之UI线程和Worker线程交互

    哈哈,博文取了个比较霸气的名字,大家不都喜欢这样忽悠人吗 呵呵! 好了,现在就是很简单的点击查询,然后这个查询有点花时间,不想见面出现假死现象,所以在另外的线程进行查询. 好了,代码在此: packa ...

  7. Android允许在UI线程中使用网络访问

    StrictMode.ThreadPolicy policy=new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode ...

  8. Android UI线程和非UI线程

    Android UI线程和非UI线程 UI线程及Android的单线程模型原则 当应用启动,系统会创建一个主线程(main thread). 这个主线程负责向UI组件分发事件(包括绘制事件),也是在这 ...

  9. Android中UI线程与后台线程交互设计的5种方法

    我想关于这个话题已经有很多前辈讨论过了.今天算是一次学习总结吧. 在android的设计思想中,为了确保用户顺滑的操作体验.一 些耗时的任务不能够在UI线程中运行,像访问网络就属于这类任务.因此我们必 ...

随机推荐

  1. Median of Two Sorted Arrays(Java)

    求2个数组的中位数 方法很多 但是时间复杂度各异 1利用数组copy方法先融合两个数组,然后排序,找出中位数 import java.lang.reflect.Array; import java.u ...

  2. 转:C#: static关键字的作用

    tatic意思是静态,可以修饰类.字段.属性.方法 标记为static的就不用创建实例对象调用了,可以通过类名直接点出来 static三种用法: 1.用于变量前,表示每次重新使用该变量所在方法.类或自 ...

  3. Android 轮询之 Service + AlarmManager+Thread (转)

    android中涉及到将服务器中数据变化信息通知用户一般有两种办法,推送和轮询. 消息推送是服务端主动发消息给客户端,因为第一时间知道数据发生变化的是服务器自己,所以推送的优势是实时性高.但服务器主动 ...

  4. (转载)C++之tinyXML使用

     tinyXML一款很优秀的操作C++类库,文件不大,但方法很丰富,和apache的Dom4j可以披靡啊!习惯了使用java类库的我看到这么丰富的c++类库,很高兴!它使用很简单,只需要拷贝几个文件到 ...

  5. 解决rsync 同步auth failed on module问题

    今天在同步备份文件时遇到一个情况,以前正常的备份,在昨天突然同步备份文件失败了.于是开始检查原因..... 报错日志/var/log/rsyncd.log发现错误 // :: [] auth fail ...

  6. Android 部分机型GridView四周默认间距

    在测试兼容性时候,部分机型,比如联想和一加等手机,在使用Gridview的时候,会默认四周有默认边距,10dp左右. 这时候需要设置 android:listSelector="@andro ...

  7. Django 1.6 基于类的通用视图

    Django 1.6 基于类的通用视图 最初 django 的视图都是用函数实现的,后来开发出一些通用视图函数,以取代某些常见的重复性代码.通用视图就像是一些封装好的处理器,使用它们的时候只须要给出特 ...

  8. MySQL query_cache_type 详解

    MySQL设置查询缓存的用意: 把查询到的结果缓存起来,下次再执行相同查询时就可以直接从结果集中取:这样就比重新查一遍要快的多. 查询缓存的最终结果是事与愿违: 之所以查询缓存并没有能起到提升性能的做 ...

  9. Oracle EBS-SQL (INV-11):检查子库存会计信息.sql

    select          OOD.ORGANIZATION_CODE                                               库存组织代码,          ...

  10. KeybMap 键盘映射工具更新至 V1.5(修订)

    KeybMap 更新至 V1.5,主要是增加了对一些多媒体键定义修改功能,也可以将任意一键定义为打开指定的程序. 3月9日略做修订. http://www.mympc.org/down/1/2005- ...