`
aliusa
  • 浏览: 84845 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Android UI Operation in Thread

阅读更多
Android UI Operation in Thread

[color=red]纯属转载http://hi.baidu.com/hi_android/blog/item/317526ea03c29f06fcfa3cc6.htmlcolor]

本文讨论Android应用程序的线程模型以及应用程序应该如何创建工作线程而不是使用主线程来处理长期运行的操作, 以得到好的UI性能. 本文还解释了你可以用来和Android UI组件交互以及创建线程的 API.

The UI thread UI 线程
当一个应用程序启动时, 系统创建一个叫做"main"的线程. 这个主线程也叫UI线程, 它非常重要, 因为它负责将事件分发给合适的widget来处理, 包括绘图事件等. 它也是你的应用程序和运行中的Android UI组件进行交互的线程. 例如, 如果你按下屏幕上的按钮, UI线程会将这个触摸事件分配给该widget, 而该widget将设置它的按下状态并向事件队列一个重绘请求. UI线程从队列中取出请求并通知widget来重画自身.

单线程模型可能会导致性能很差, 除非你的程序被正确的实现. 特别的, 如果每件事都在同一个线程中进行, 那么耗时长的操作(例如网络访问和数据库查询)将阻塞UI线程, 从而使整个UI无法交互. 在耗时操作进行时, 包括绘画事件在内的所有事件都无法进行分配. 在用户看来, 该应用程序停止了响应. 更糟糕的是, 如果UI线程被阻塞超过一段时间(当前的限制是5秒钟), 那么用户将看到"应用程序无响应"的对话框.

如果你希望看看这是多么的糟糕, 那么你可以写一个程序, 创建一个按钮, 它的OnClickListener中调用Thread.sleep(2000). 那么该按钮在按下去以后要等2秒才会谈起, 这时候用户是非常容易感觉到程序很慢.

总之, 应用程序UI的响应速度是很重要的, 所以应该避免阻塞UI线程. 如果你需要进行耗时操作, 那么你应该在其他的线程中进行(后台或者工作线程).

下面的例子演示了如何实现一个单击监听器来下载一个图片并将它显示在 ImageView中:


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


----------------------------------------------------------------------
一开始, 这段代码看起来是个不错的解决方案, 因为它不会阻塞线程. 不幸的是, 它破坏了UI的单线程模型: Android UI工具不是线程安全的, 必须在UI线程中操作. 在上面的代码段中, ImageView在一个工作线程中操作, 这回导致很奇怪的问题. 追踪和解决这样的bug是非常困难的.

Android提供了一些从其它线程中访问UI线程的方法. 你可能已经对它们之中的某些比较熟悉了:

Activity.runOnUiThread(Runnable) 
View.post(Runnable) 
View.postDelayed(Runnable, long) 
Handler 

你可以使用上面的任意一种类和方法来改正之前的错误:


----------------------------------------------------------------------
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();
}


----------------------------------------------------------------------
不幸的是, 这些类和方法也会使你的代码更加复杂. 如果你需要实现频繁的UI更新的话就更糟糕了.

为解决这个问题, Android1.5以上的平台提供了一个叫做AsyncTask的工具类.

Android1.0和1.1上也有和它等效的类叫做UserTask, 它提供了完全一样的接口.

AsyncTask的作用是帮你来管理线程. 我们将之前的例子用AsyncTask来重写:


----------------------------------------------------------------------
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);
}
}


----------------------------------------------------------------------
AsyncTask必须使用创建子类的方式来使用. AsyncTask实例只能在UI线程中创建,并且只能运行一次. AsyncTask documentation 中有它的详细介绍, 这里简单介绍一下:

你可以使用泛型来指定任务的参数的类型, 过程值和最终值. (不知道理解的对不对 You can specify the type, using generics, of the parameters, the progress values and the final value of the task.)
doInBackground() 方法自动运行在一个工作线程中. 
onPreExecute(), onPostExecute() 和onProgressUpdate() 都在UI线程中工作. 
 doInBackground() 的返回值被传给 onPostExecute()你可以在任何时间在doInBackground()中调用publishProgress() 来在 UI 线程中运行 onProgressUpdate() .


你可以在任何线程中取消该工作.
无论你是否使用 AsyncTask, 记住以下关于单线程模型的两条规则:

不要阻塞UI线程, 以及
确定你只在UI线程中访问Android UI 工具.

AsyncTask 只是让上面两件事情变得更加方便
分享到:
评论

相关推荐

    onethread

    例如,在UI更新中,Android系统默认采用主线程,也称为UI线程,处理用户交互和界面更新。使用单线程模型,可以确保所有UI操作都在同一个线程中完成,防止因线程间竞争导致的界面卡顿或无响应。 然而,单线程模型也...

    PDF-MigratingToSwiftFromAndroid-英文版.rar

    同时,Swift中处理多线程主要使用GCD(Grand Central Dispatch)和OperationQueue,与Android的AsyncTask和Thread有异同。 10. **测试与部署**: iOS应用的测试包括单元测试、UI测试和App Store审核流程。开发者...

    跨线程调用控件的四种方式.rar

    由于Windows Forms和WPF的控件是线程安全的,它们必须在创建它们的同一线程中进行操作,否则会抛出“Cross-thread operation not valid”异常。下面我们将详细探讨四种在C#中实现跨线程调用控件的方法。 1. **...

    仿微信首页

    Android有AsyncTask、Thread或Handler,iOS有GCD(Grand Central Dispatch)和OperationQueue来实现这一目标。 9. **权限管理**:在Android系统中,开发者需要处理运行时权限,例如读写存储、网络访问等。而iOS也有...

    backgroundworker

    2. **OperationQueue**: 类似于GCD,但提供了更多的控制和灵活性,如依赖关系、优先级、取消操作等。 3. **NSOperation/NSOperationQueue**: 这些是面向对象的版本,允许创建自定义操作类,并能与其他操作进行协调...

    简单图库源码

    Android使用`AsyncTask`或`Thread`,iOS使用`OperationQueue`或`Grand Central Dispatch (GCD)`。 9. **UI设计**:界面设计应简洁易用,考虑用户交互,如点击反馈、加载动画等。 10. **适配多种屏幕尺寸**:应用...

    图片拍照上传、访问相册的实现

    - 为了不阻塞UI线程,图片的加载、处理和上传应该在后台线程执行,Android可以使用`AsyncTask`或`Thread`,iOS可以使用`Grand Central Dispatch (GCD)`或`OperationQueue`。 7. **用户体验**: - 提供预览功能:...

    模仿QQ客户端开发

    在Java中,可以使用Thread类或ExecutorService,而在iOS中,可以使用OperationQueue。 5. **数据库管理**:用户信息、好友关系、聊天记录等需要持久化存储,因此需要熟悉SQL数据库,如SQLite或MySQL,或者NoSQL...

Global site tag (gtag.js) - Google Analytics