Android ANR keyDispatchingTimedOut Error 之 Painless Threading

最近在开发 Android 项目时,遇到了一个偶尔会出现的 Android ANR keyDispatchingTimedOut Error 错误,在网上搜索过后找到了一个相同问题的帖子,参见

http://stackoverflow.com/questions/4529770/android-anr-keydispatchingtimedout-error-while-continuous-tapping-on-screen,

该帖子遇到的问题正好是我遇到的问题,通读帖子的回答,发现是 Thread 方面的问题,转到 Android 开发官方文档,参见

http://developer.android.com/resources/articles/painless-threading.html,

读完官方文档后即发现了自己的错误所在。

原文如下:

Painless Threading

This article discusses the threading model used by Android applications and how applications can ensure best UI performance by spawning worker threads to handle long-running operations, rather than handling them in the main thread. The article also explains the API that your application can use to interact with Android UI toolkit components running on the main thread and spawn managed worker threads.

The UI thread

When an application is launched, the system creates a thread called"main" for the application. The main thread, also called theUIthread, is very important because it is in charge of dispatching theevents to the appropriate widgets, including drawing events.It is also the thread where your application interacts with running components of the Android UI toolkit.

For instance, if you touch the a button on screen, the UI thread dispatchesthe touch event to the widget, which in turn sets its pressed state andposts an invalidate request to the event queue. The UI thread dequeuesthe request and notifies the widget to redraw itself.

This single-thread model can yield poor performance unless your application is implemented properly. Specifically, if everything is happening in a single thread, performing long operations such as network access or databasequeries on the UI thread will block the whole user interface. No eventcan be dispatched, including drawing events, while the long operationis 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 invokesThread.sleep(2000) in its OnClickListener.The button will remain in its pressed state for about 2 seconds beforegoing back to its normal state. When this happens, it is very easy forthe user toperceive the application as slow.

To summarize, it's vital to the responsiveness of your application's UI tokeep the UI thread unblocked. If you have long operations to perform, you shouldmake sure to do them in extra threads (background orworkerthreads).

Here's an example of a click listener downloading an image over the network and displaying it in anImageView:

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 doesnot block the UI thread. Unfortunately, it violates the single-threaded modelfor the UI: the Android UI toolkit isnot thread-safe and must alwaysbe manipulated on the UI thread. In this piece of code above, theImageView is manipulated on a worker thread, which can cause reallyweird problems. Tracking down and fixing such bugs can be difficult andtime-consuming.

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

You can use any of these classes and methods to correct the 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 could also tend to make your code more complicatedand more difficult to read. It becomes even worse when your implementcomplex operations that require frequent UI updates.

To remedy this problem, Android 1.5 and later platforms offer a utility classcalledAsyncTask, that simplifies the creation oflong-running tasks that need to communicate with the user interface.

An AsyncTask equivalent is also available for applications thatwill run on Android 1.0 and 1.1. The name of the class isUserTask. It offers theexact same API and all you have to do is copy its source code in yourapplication.

The goal of AsyncTask is to take care of thread management foryou. 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, Void, Bitmap> { 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 subclassingit. It is also very important to remember that anAsyncTaskinstance has to be created on the UI thread and can be executed only once. Youcan read theAsyncTask 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.java,PhotostreamActivity.java and ViewPhotoActivity.java). We 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:

  1. Do not block the UI thread, and
  2. Make sure that you access the Android UI toolkit only on the UI thread.

AsyncTask just makes it easier to do both of these things.



转载于:https://www.cnblogs.com/myittec/archive/2011/09/18/2392859.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值