英语原文共 16 页,剩余内容已隐藏,支付完成后下载完整资料
Android Handler Internals
要使Android应用程序能够响应,你需要防止UI线程的阻塞。当阻塞或计算密集型任务被加载到工作线程时,响应性也会增加。 这些操作的结果通常需要更新UI组件,而这些也必须在UI线程上执行。 阻塞队列,共享内存和管道等机制也会使得UI线程阻塞。 为了防止这个问题,Android提供了自己的消息传递机制 - the Handler。 Handler是Android Framework层的一个基本组成部分。它提供了非阻塞消息传递机制。 在生产者和消费者在传递消息时都不会出现阻塞。
虽然Handler群经常会被人使用,但却很容易忽略它们的工作原理。这篇文章则是更深入地了解Handler的各种组件。 它解释了为什么Handler作为一个强大的组件来为工作线程和UI线程之间进行通信。
使用ImageView控件的例子
让我们从一个例子中,了解如何在应用程序中使用Handler。我们可以先思考一下从网络获取的图像信息并显示到控件上的活动。有几种方法可以做这个。在这个例子中,我们将启动一个新的工作线程来执行网络调用并检索图像有效载荷。
public class MainActivity extends AppCompatActivity {
private static final String IMAGE_URL = '···';
private ProgressBar progressIndicator;
private ImageView imageView;
private Handler handler;
class ImageFetcher implements Runnable {
final String url;
ImageFetcher(String url) {
this.url = url;
}
@Override
public void run() {
// download image -- code removed
final Bitmap bitmap = BitmapFactory.decodeStream(inputstream);
handler.post(new Runnable() {
@Override
public void run() {
imageView.setImageBitmap(bitmap);
}
});
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Thread workerThread = new Thread(new ImageFetcher(IMAGE_URL));
workerThread.start();
}
}
另一种方法是使用Handler Messages而不是Runnables。
public class MainActivity extends AppCompatActivity {
private static final String IMAGE_URL = '···';
private static final int MSG_SHOW_PROGRESS = 1;
private static final int MSG_SHOW_IMAGE = 2;
private ProgressBar progressIndicator;
private ImageView imageView;
private Handler handler;
class ImageFetcher implements Runnable {
final String url;
ImageFetcher(String url) {
this.url = url;
}
@Override
public void run() {
handler.obtainMessage(MSG_SHOW_PROGRESS).sendToTarget();
// download image -- code removed
final Bitmap bitmap = BitmapFactory.decodeStream(inputstream);
handler.obtainMessage(MSG_SHOW_IMAGE, bitmap).sendToTarget();
}
}
class UI Handler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SHOW_PROGRESS: {
progressIndicator.setVisibility(View.VISIBLE);
break;
}
case MSG_SHOW_IMAGE: {
progressIndicator.setVisibility(View.GONE);
imageView.setImageBitmap((Bitmap) msg.obj);
break;
}
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new UI Handler();
final Thread workerThread = new Thread(new ImageFetcher(IMAGE_URL));
workerThread.start();
}
}
在第二个例子中,是工作线程直接从网络中获取图像。 一旦图像信息下载到本地,我们需要使用位图来更新ImageView控件显示的内容。我们知道我们从非UI线程时无法操作UI组件的,所以我们使用一个Handler程序Handler。 Handler在工作线程和UI线程之间作为调解人。而消息则是由Handler在工作线程中进入队列,之后在UI线程中取出进行处理。
深入了解Handler内部
Handler包含的组件是:
- Handler
- Message
- Message Queue
- Looper
我们将看看每个组件,看看它们之间的相互作用。
Handler
handler是线程之间消息传递的一个直接接口。两个消费者和生产者线程通过调用以下操作与Handler程序进行信息的交互:
-从消息队列创建,插入或删除消息
-处理消费者线程上的消息
每一个的Handler会与Looper和Message Queue相关联。创建Handler对象有两种方式。
-通过默认构造函数,它使用与当前线程相关联的Looper
-通过明确指定使用哪个Looper1
Handler是无法使用Looper的功能,因为它不能将消息放入消息队列中去。 因此,它并不会收到任何消息并进行处理。
public Handler(Callback callback, boolean async) {
// code removed for simplicity
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException( “Canrsquo;t create handler inside thread that has not called Looper.prepare()”);
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
Android Source(上图)的片段演示了构建新的代码的逻辑处理者,Handler在检查当前线程是否有有效的Looper。 如果没有,它会抛出一个运行时异常。 然后,Handler接收到Looper的消息队列的一个引用。
注意:与同一线程相关联的多个Handler共享相同的一个消息队列,因为他们共享同一个Looper。回调是一个可选参数,如果提供,它将处理发送消息的Looper。
Message
Message是作为一个可以包含任意数据的容器。 生产者线程将消息发送到Handler程序,那么该Handler程序将消息排队到消息队列中。 消息可以提供三个额外的信息,这三个信息是Handler程序和消息队列处理消息所要求包含的信息:
- what 是Handler可以使用的标识符来区分消息并处理它们不同
- time 通知消息队列何时处理消息
- target 指示Handler程序应处理消息
消息对象的创建通常使用Handler程序以下的方法之一:
public final Message obtainMessage()
public final Message obtainMessage(int what)
public final Message obtainMessage(int what, Object obj)
public final Message obtainMessage(int what, int arg1, int arg2)
public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
消息是从消息池获得的,上面的函数提供的参数则是用来填充消息的内容字段。 Handler程序还将Message的目标设置为自身,在这里我们呼吁大家使用一下的方法完成:
mHandler.obtainMessage(MSG_SHOW_IMAGE, mBitmap).sendToTarget();
消息池是最大池大小为50的消息对象的链接列表用来让Handler程序处理消息,消息队列将对象返回到消息池并重置所有的消息数据。
当通过post(Runnable r)向Handler程序发布Runnable对象时,Handler程序会隐式地构造一个新的消息对象,同时它还设置回调字段,用来保存Runnable对象。
Message m = Message.obtain();
m.callback = r;
<!--
剩余内容已隐藏,支付完成后下载完整资料
资料编号:[137771],资料为PDF文档或Word文档,PDF文档可免费转换为Word
以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。
您可能感兴趣的文章
- 为非政府组织OG慈善基金会设计的基于社区的救灾管理系统外文翻译资料
- 基于UML建模的医疗系统电子健康服务软件外文翻译资料
- 开发一种具有增强现实功能的智能手机应用程序, 以支持护理学生对心衰的虚拟学习外文翻译资料
- 在开发 Web 应用程序中应用 Vue.JS 框架外文翻译资料
- 基于MES系统的生产车间信息管理研究外文翻译资料
- 基于Vue.js和MySQL的电子商务平台的设计与实现外文翻译资料
- 详细的Spring配置和SpringBoot外文翻译资料
- 基于NS2的DSR和AODV协议的性能比较研究外文翻译资料
- 不同仿真参数下NS2的TCP吞吐量性能外文翻译资料
- 基于Spring Boot和VUE的车辆管理系统实现外文翻译资料