Whenever you first start an Android application, a thread called "main" is automatically created. The main thread, also called the UI thread, is very important because it is in charge of dispatching the events to the appropriate widgets and this includes the drawing events. It is also the thread you interact with Android widgets on. For instance, if you touch the a button on screen, the UI thread dispatches the touch event to the widget which in turn sets its pressed state and posts an invalidate request to the event queue. The UI thread dequeues the request and notifies the widget to redraw itself.

This single thread model can yield poor performance in Android applications that do not consider the implications. Since everything happens on a single thread performing long operations, like network access or database queries, on this thread will block the whole user interface. No event can be dispatched, including drawing events, while the long operation is underway. From the user's perspective, the application appears hung. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog.

If you want to see how bad this can look, write a simple application with a button that invokes Thread.sleep(2000) in itsOnClickListener. The button will remain in its pressed state for about 2 seconds before going back to its normal state. When this happens, it is very easy for the user to perceive the application as slow.

Now that you know you must avoid lengthy operations on the UI thread, you will probably use extra threads (background orworker threads) to perform these operations, and rightly so. Let's take the example of a click listener downloading an image over the network and displaying it in an ImageView:

public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap(b);
}
}).start();
}

At first, this code seems to be a good solution to your problem, as it does not block the UI thread. Unfortunately, it violates the single thread model: the Android UI toolkit is not thread-safe and must always be manipulated on the UI thread. In this piece of code, the ImageView is manipulated on a worker thread, which can cause really weird problems. Tracking down and fixing such bugs can be difficult and time-consuming.

Android offers several ways to access the UI thread from other threads. You may already be familiar with some of them but here is a comprehensive list:

Any of these classes and methods could be used to correct our previous code example:

public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork();
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(b);
}
});
}
}).start();
}

Unfortunately, these classes and methods also tend to make your code more complicated and more difficult to read. It becomes even worse when your implement complex operations that require frequent UI updates. To remedy this problem, Android 1.5 offers a new utility class, called AsyncTask, that simplifies the creation of long-running tasks that need to communicate with the user interface.

AsyncTask is also available for Android 1.0 and 1.1 under the name UserTask. It offers the exact same API and all you have to do is copy its source code in your application.

The goal of AsyncTask is to take care of thread management for you. Our previous example can easily be rewritten withAsyncTask:

public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
} private class DownloadImageTask extends AsyncTask<string, bitmap="" void,=""> {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
} protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}

As you can see, AsyncTask must be used by subclassing it. It is also very important to remember that an AsyncTask instance has to be created on the UI thread and can be executed only once. You can read the AsyncTask documentation for a full understanding on how to use this class, but here is a quick overview of how it works:

In addition to the official documentation, you can read several complex examples in the source code of Shelves (ShelvesActivity.java and AddBookActivity.java) and Photostream (LoginActivity.javaPhotostreamActivity.java andViewPhotoActivity.java). I highly recommend reading the source code of Shelves to see how to persist tasks across configuration changes and how to cancel them properly when the activity is destroyed.

Regardless of whether or not you use AsyncTask, always remember these two rules about the single thread model: do not block the UI thread and make sure the Android UI toolkit is only accessed on the UI thread. AsyncTask just makes it easier to do both of these things.

在Main Thread中使用异步的更多相关文章

  1. Service 是否在 main thread 中执行, service 里面是否能执行耗时的操作?

    默认情况,如果没有显示的指 service 所运行的进程, Service 和 activity 是运行在当前 app 所在进程的 main thread(UI 主线程)里面.service 里面不能 ...

  2. C#中的线程一(委托中的异步)

    C#中的线程一(委托中的异步) 一.同步委托 我们平时所用的委托以同步居多,我们编写一个方法和相关委托进行演示: publicdelegatevoid DoSomethingDelegate(stri ...

  3. jupyter notebook中出现ValueError: signal only works in main thread 报错 即 长时间in[*] 解决办法

    我在jupyter notebook中新建了一个基于py3.6的kernel用来进行tensorflow学习 但是在jupyter notebook中建立该kernel时,右上角总是显示 服务正在启动 ...

  4. iOS 报错:(子线程中更新UI)This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.

    今天在写程序的时候,使用Xcode 运行工程时报出下面的错误错信息,我还以为是什么呢,好久没遇到过这样的错误了. **ProjectName[1512:778965] This application ...

  5. .NET中的异步

    .NET中4种异步方式? ThreadPool.QueueUserworkItem实现 APM模式(就是BeginXXX和EndXXX成对出现.) EAP模式(就是Event based, 准确说来就 ...

  6. Java多线程2:Thread中的实例方法

    Thread类中的方法调用方式: 学习Thread类中的方法是学习多线程的第一步.在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别: 1 ...

  7. .Net中的异步编程总结

    一直以来很想梳理下我在开发过程中使用异步编程的心得和体会,但是由于我是APM异步编程模式的死忠,当TAP模式和TPL模式出现的时候我并未真正的去接纳这两种模式,所以导致我一直没有花太多心思去整理这两部 ...

  8. 2.Thread中的实例方法

    (转自:http://www.cnblogs.com/xrq730/p/4851233.html) Thread类中的方法调用方式: 1.this.XXX 这种调用方式表示的线程是:线程实例本身 2. ...

  9. Java多线程3:Thread中的实例方法

    一.Thread类中的方法调用方式 学习Thread类中的方法是学习多线程的第一步.在学习多线程之前特别提出一点,调用Thread中的方法的时候,在线程类中,有两种方式,一定要理解这两种方式的区别: ...

随机推荐

  1. NIUDAY 11.23 北京站抢票啦 | 看 AI 落地行业 享 AI 时代红利

    2018 年是见证「奇迹」的一年.AI 从多年的热门话题中开始走下神坛,逐渐深入到了各个行业,加速经济结构优化及行业智慧化升级,AI 已不再是难以企及的神话而是可触摸的美好未来. 政策支持加上资本推动 ...

  2. bzoj1708 [Usaco2007 Oct]Money奶牛的硬币 背包dp

    [Usaco2007 Oct]Money奶牛的硬币 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 852  Solved: 575[Submit][Sta ...

  3. 【HDOJ6298】Maximum Multiple(数论)

    题意:给定n,求x,y,z三个整数,使得x|n,y|n,z|n,且xyz最小 n<=1e6 思路: 不定方程1/x+1/y+1/z=1 只有(2,3,6)(2,4,4) (3,3,3)三组正整数 ...

  4. PHP获得真实客户端的真实IP REMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR[]转载

    REMOTE_ADDR 是你的客户端跟你的服务器“握手”时候的IP.如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP. HTTP_CLIENT_IP 是代理服务器发送的HTTP头. ...

  5. vagrant的学习 之 Laravel

    vagrant的学习 之 Laravel 本文根据慕课网的视频教程练习,感谢慕课网! 慕课视频学习地址:https://www.imooc.com/video/14218. 慕课的参考文档地址:htt ...

  6. PAT (Advanced Level) 1031. Hello World for U (20)

    简单题. #include<iostream> #include<cstring> #include<cmath> #include<algorithm> ...

  7. 洛谷—— P1785 漂亮的绝杀

    https://www.luogu.org/problem/show?pid=1785 题目背景 话说absi2011的企鹅在和斗神塔第60层的Boss战斗 不好,这局要输了,企鹅还剩4血了Boss还 ...

  8. Spring中实现自定义事件

    原理: 通过扩展ApplicationEvent,创建一个事件类CustomEvent.这个类必须定义一个默认的构造函数,它应该从ApplicationEvent类中继承的构造函数. 一旦定义事件类, ...

  9. send-mail: fatal: parameter inet_interfaces: no local interface found for ::1

    转载:http://blog.csdn.net/csdnones/article/details/50717934 发送邮件: [root@iZ23whn33jnZ log]# echo '这是邮件标 ...

  10. win8系统 如何不显示这台电脑的文件夹

    在win8系统中,默认有下面这种文件夹   只要打开注册表编辑器,找到下面所示的项目,删除所有子文件夹即可(最后剩下一个DelegateFolders不用管) [HKEY_LOCAL_MACHINE\ ...