Drawable Mutations
这篇文章将讨论Android应用程序中使用的线程模型,并讨论如何确保应用程序最佳的UI呈现(通过创建工作者线程来处理耗时的操作,而不是在主线程里处理)。这篇文章还将阐述与运行在主线程中的UI组件交互的API以及创建托管的工作者线程的API。
UI线程
当应用程序启动后,系统创建了一个叫做“main”的线程。主线程,也叫UI线程,非常重要,因为它负责分发事件给构件,包括绘制事件。也是这个线程,在这里才能与Android UI工具包中的组件进行交互。
例如,当你触摸屏幕上的一个按钮时,UI线程会分发一个触摸事件给构件,然后,构件会设定自己为被按下的状态,并抛出一个显示无效的请求给事件队列。UI线程队列请求并通知构件绘制自己。
单线程模型会导致性能低下,除非你的程序很好地实现。特别是,当所有的操作都在单一的线程中进行,耗时的操作(如网络访问、数据查询)会阻塞UI。在耗时操作执行时,没有任何事件可以分发,包括绘制的事件。从用户的视觉来看,应用程序被挂起了。更糟糕的是,如果UI线程阻塞超过一定的时间(现在大约是5秒钟),系统会给用户呈现一个糟糕的“应用程序无响应”(ANR)对话框。
如果你想看这有多糟糕,你可以写一个简单的应用程序,在一个Button的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线程。遗憾的是,它违背了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。
为了解决这个问题,Android 1.5和它之后的平台提供了一个通用的类——AsyncTask,其简化了长时间运行任务的创建过程,而这些任务还能做到与UI进行交互。
在Android 1.0和1.1上,也有与AsyncTask类似的东西,叫做UserTask。它提供了相同的API,而你需要做的只是拷贝其中的代码。
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的文档来全面了解如何使用,但这里,只是简要地描述它以及它的工作过程:
·你可以使用泛型来指定参数、进度值和最终结果的类型
·doInBackground() 方法自动在工作者线程中执行
·onPreExecute(),onPostExecute()和onProgressUpdate()在主线程中调用
·doInBackground()中返回的值会发送给onPostExecute()方法
·你可以在doInBackground()中随时调用publishProgress()来执行onProgressUpdate()
·你可以任何时候从任何线程中取消任务
除了官方的文档,你还可以参考几个复杂例子的源代码,如Shelves(ShelvesActivity.java和AddBookActivity.java)和Photostream(LoginActivity,PhotostreamActivity.java和ViewPhotoActivity.java)。我们强烈地建议你阅读Shelves的源代码,来了解配置变更时任务的保存以及Activity销毁时如何正确地取消任务。
不管你是否使用AsyncTask,在单线程模型中始终要记住两条法则:
1.不要阻塞UI线程
2.确保只在UI线程中访问Android UI工具包
分享到:
相关推荐
"Drawable Mutations"是关于如何管理和优化Drawable对象的一个关键概念,尤其是在处理多个引用相同Drawable对象的情况时。这篇博客文章可能深入解析了Android SDK文档中关于Drawable Mutations的细节。 Drawable ...
在Android开发中,Drawable是图形和图像处理的重要组成部分,它是一种可以绘制到Canvas上的对象,广泛用于界面元素的装饰和状态表示。以下是对Android中drawable集合的详细解释: 1. **Bitmap Drawable**: Bitmap ...
在Android开发中,Drawable是图形和图像对象的抽象表示,用于在用户界面上创建各种视觉效果。本篇文章将深入探讨Android中的Drawable及其使用方法,包括系统提供的各种Drawable类型以及如何自定义Drawable。 首先,...
在Android开发中,Drawable是图形资源的核心组成部分,用于在用户界面上绘制各种图像,如按钮、背景、图标等。理解并熟练运用Drawable的各种高效用法对于优化应用性能和提升用户体验至关重要。以下是一些关于Android...
在Android开发中,`drawable`资源是至关重要的组成部分,它主要负责存储应用程序中的各种图形元素,如图标、背景、按钮形状等。`drawable`资源通常存储在项目的`res/drawable`目录下,并且根据不同的密度(ldpi, ...
在Android开发中,`Drawable`是一个非常重要的概念,它代表了屏幕上的图形对象,可以是图像、颜色、形状或者是它们的组合。`Drawable`广泛应用于各种UI元素的背景、图标等,提供了丰富的自定义和动画效果。在这个...
在Android开发中,Drawable是用于绘制图形的资源,它们被广泛应用于各种界面元素的背景或图片显示。Drawable资源是抽象的图形对象,可以包括图片、颜色、渐变等多种形式。在Android SDK中,开发者通常不需要直接操作...
在Android开发中,`drawable`文件是一个至关重要的组成部分,它主要负责应用的图形资源管理。`Drawable`资源是Android系统中用于表示图形的一种抽象概念,它可以是图片、颜色、形状或者动画等。在这个主题中,我们将...
在Android开发中,Drawable是图形对象的抽象表示,通常用于设置视图的背景、图标的样式等。自定义Drawable能够让我们根据项目需求创造出独特的视觉效果,例如标题中提到的圆角图片和圆形图片。本篇将深入探讨如何...
在Android开发中,Drawable资源是用于管理应用中各种图形元素,如图片、颜色、形状等的关键组成部分。了解和熟练掌握Drawable资源的管理与图片处理,对于优化应用性能和提升用户体验至关重要。以下是一些关于...
在Android开发中,`Drawable`是一个非常重要的概念,它代表了可以绘制到屏幕上的图形对象。这个示例项目"android drawable"旨在展示如何在Android应用中有效地使用和显示`Drawable`资源。 `Drawable`在Android中...
在Android开发中,`drawable`资源是至关重要的组成部分,它主要负责存储应用程序中使用的各种图形元素,如图标、背景图片等。本知识点将深入探讨`drawable`资源的使用、分类和适应不同屏幕密度的重要性。 首先,`...
在Android开发中,Drawable是图形和图像处理的重要组成部分,它涵盖了多种类型的图像资源,如颜色、形状、位图等。本篇文章将深入探讨Android的Drawable及其应用,通过一个实际的Demo来展示其功能和用法。 Drawable...
在Android开发中,自定义Drawable是提升应用UI个性化和性能优化的重要手段。本文将深入探讨如何通过自定义Drawable实现图片的圆角、圆形以及椭圆形显示,帮助开发者更好地理解和运用这一技术。 首先,我们了解...
在Android应用开发中,Drawable是用于图形和图像处理的核心组件,尤其在UI设计和交互中扮演着重要角色。本资源包“android安卓APP之13种Drawable位图片资源.zip”涵盖了Android开发中常见的13种Drawable类型,这些...
在Android开发中,Drawable是图形对象的抽象表示,用于在界面上绘制各种图像,如背景、按钮、图标等。理解并熟练使用不同类型的Drawable对于优化应用的视觉效果和性能至关重要。下面将详细介绍Android中常见的...
在Android开发中,Drawable是图形和图像的基本元素,它用于绘制视图的背景、按钮、图标等。系统提供了多种预定义的Drawable类型,如Shape、BitmapDrawable等,但有时我们可能需要实现更复杂的视觉效果,这时就需要...
### Drawable与Bitmap之间的转换 在Android开发过程中,经常会遇到图像处理的需求,比如将应用程序中的图标、背景图等进行转换和操作。其中,`Drawable`和`Bitmap`是两种常见的图像对象类型,它们各自有着不同的...
`DrawableTextView.zip` 提供了一个自定义的控件示例,名为`DrawableTextView`,该控件实现了图片(Drawable)与文本居中对齐的功能。这个功能在很多应用场景中都非常实用,比如设置带有图标的通知或者状态提示。 `...