Android多线程分析之一:使用Thread异步下载图像

CC 许可,转载请注明出处
 

打算整理一下对 Android Framework 中多线程相关知识的理解,主要集中在 Framework 层的 Thread, Handler, Looper, MessageQueue, Message, AysncTask,当然不可避免地要涉及到 native 方法,因此也会分析 dalvik 中和线程以及消息处理相关的代码:如 dalvik 中的 C++ Thread 类以及 MessageQueue 类。本文将从一个使用 Thread 的简单 应用入手,引入 Thread 这个话题,接下来的几篇文章会依次介绍前面提到的那些主题。

这是一个使用 Android Thread 从网络上异步下载图片并在 ImageView 中显示的的简单示例。因为需要访问网络,所以要在 manifest.xml 中添加网络访问权限:

	<uses-permission android:name="android.permission.INTERNET">
</uses-permission>

布局文件很简单,一个 Button,一个 ImageView:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dip" > <Button
android:id="@+id/LoadButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Load">
</Button> <ImageView
android:id="@+id/ImageVivew"
android:layout_width="match_parent"
android:layout_height="400dip"
android:scaleType="centerInside"
android:padding="2dp">
</ImageView> </LinearLayout>

接下来看代码:

首先来看定义:图片的 url 路径,两个消息值以及一些控件:

    private static final String sImageUrl = "http://fashion.qqread.com/ArtImage/20110225/0083_13.jpg";

    private static final int MSG_LOAD_SUCCESS = 0;
private static final int MSG_LOAD_FAILURE = 1; private Button mLoadButton;
private ProgressDialog mProgressBar;
private ImageView mImageView;

然后来看控件的设置:

	protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Log.i("UI thread", " >> onCreate()"); mProgressBar = new ProgressDialog(this);
mProgressBar.setCancelable(true);
mProgressBar.setMessage("Image downloading ...");
mProgressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressBar.setMax(100); mImageView = (ImageView)this.findViewById(R.id.ImageVivew); mLoadButton = (Button)this.findViewById(R.id.LoadButton);
mLoadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mProgressBar.setProgress(0);
mProgressBar.show(); new Thread() {
@Override
public void run() {
Log.i("Load thread", " >> run()");
Bitmap bitmap = loadImageFromUrl(sImageUrl);
if (bitmap != null) {
Message msg = mHandler.obtainMessage(MSG_LOAD_SUCCESS, bitmap);
mHandler.sendMessage(msg);
}
else {
Message msg = mHandler.obtainMessage(MSG_LOAD_FAILURE, null);
mHandler.sendMessage(msg);
}
}
}.start();
}
});
}

loadImageFromUrl 是一个从网络下载 Bitmap 的 static 函数:

    static Bitmap loadImageFromUrl(String uil) {
Bitmap bitmap = null;
try{
InputStream in = new java.net.URL(sImageUrl).openStream();
bitmap = BitmapFactory.decodeStream(in);
in.close();
}
catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}

mHandler 是主线程也就是 UI 线程中处理自定义消息的 Handler:

    private Handler mHandler= new Handler(){
@Override
public void handleMessage(Message msg) {
Log.i("UI thread", " >> handleMessage()"); switch(msg.what){
case MSG_LOAD_SUCCESS:
Bitmap bitmap = (Bitmap) msg.obj;
mImageView.setImageBitmap(bitmap); mProgressBar.setProgress(100);
mProgressBar.setMessage("Image downloading success!");
mProgressBar.dismiss();
break; case MSG_LOAD_FAILURE:
mProgressBar.setMessage("Image downloading failure!");
mProgressBar.dismiss();
break;
}
}
};

纵观上面的代码,当点击 load 按钮时,会创建一个匿名 Thread,并调用其 start() 启动运行线程,在这个线程中进行图像下载并解码成 Bitmap,然后通过 Handler 向 UI 线程发送消息以通知下载结果。这都是在匿名 Thead 中处理的。主线程也就是 UI 线程收到消息之后,会分发给 Handler,在它的 handleMessage 方法中根据消息 id 来处理下载结果,要么成功要么失败,并相应地更新 UI。运行该示例,你可以从 logcat 中看到 UI thread 和 Load thread 的线程id 是不同的,因为它们是两个独立的线程。

在匿名线程下载完毕之后,为什么不直接在这个线程的 run() 中更新 UI 呢?这样做有什么后果?这些问题将在后文详细解答。

Android多线程分析之一:使用Thread异步下载图像的更多相关文章

  1. Android多线程分析之中的一个:使用Thread异步下载图像

    Android多线程分析之中的一个:使用Thread异步下载图像 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可.转载请注明出处 打算整理一下对 Android Fr ...

  2. Android多线程分析之五:使用AsyncTask异步下载图像

    Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...

  3. Android多线程分析之二:Thread的实现

    Android多线程分析之二:Thread的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处   在前文<Android多线程分析之一 ...

  4. Android多线程分析之三:Handler,Looper的实现

    Android多线程分析之三:Handler,Looper的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前文<Android多 ...

  5. Android多线程分析之四:MessageQueue的实现

    Android多线程分析之四:MessageQueue的实现 罗朝辉 (http://www.cnblogs.com/kesalin/) CC 许可,转载请注明出处 在前面两篇文章<Androi ...

  6. Android Telephony分析(七) ---- 接口扩展(异步转同步)

    本文是基于上一篇<Android Telephony分析(六) —- 接口扩展(实践篇)>来写的.上一篇介绍的接口扩展的方法需要实现两部分代码:1. 从APP至RIL,发送请求:2. 从R ...

  7. ANDROID_MARS学习笔记_S04_009_用java.lang.ref.SoftReference作缓存,android.os.Handler和new Thread异步加载略图片

    一.简介 二.代码流程 1.private Map<String, SoftReference<Drawable>> imageCache = new HashMap<S ...

  8. UML分析AsyncDisplayKit框架-ASMuplexImageNode异步下载时序图。

    PS:博客园图片服务器不正常工作,数据上传后服务器返回http500,园方迟迟还没解决. 我从2016-01-18 05:52向园方反馈问题-请问博客园的图片服务器有在正常运行吗,至此时2016-01 ...

  9. Android四个多线程分析:MessageQueue实现

    Android四个多线程分析:MessageQueue的实现 罗朝辉 (http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 在前面两篇文章<Android多线 ...

随机推荐

  1. Kubernetes1.5正式发布

    Kubernetes1.5正式发布 修复了很多已知问题 进一步增强federation相关特性 将PetSet改名为StatefulSet 将ScheduledJobs改名为CronJobs 新增了命 ...

  2. Hibernate和jsp做数据库单表的增删改查

    虽然很基础,但是我转牛角尖了~~~~这是几个文件 1.最重要的.Java文件 package com.chinasofti.hibb.struts; import org.hibernate.Sess ...

  3. c#下调用dll动态链接库[转]

    C# 调用传统的 API 动态链接库,是.NET开发经常被讨论的问题. 比如有这么一个动态链接库(delphi 语言): library DelphiDLL; uses SysUtils, Class ...

  4. Nginx开启Gzip压缩

    .Vim打开Nginx配置文件 vim /usr/local/nginx/conf/nginx.conf .找到如下一段,进行修改 gzip on; gzip_min_length 1k; gzip_ ...

  5. iOS 的文字滚动条效果的实现

    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(50, 100, 300, 50)]; label.text  = @"欢 ...

  6. DWG2SHP DXF2SHP 如何把AutoCAD的DWG,DXF文件转换为Esri ArcGIS的Shape文件

    dwg是AutoCAD创立的一种图纸保存格式,已经成为二维CAD的标准格式,很多其他CAD为了兼容AutoCAD,也直接使用dwg作为默认工作文件. 地图shape文件由ESRI开发,一个ESRI的s ...

  7. 我与solr(二)--导入mysql数据库

    关于solr的搭建详见上一篇的随笔. 步骤1: 在webapps中solrhome下新建一个文件夹名字叫做mynode(名字不固定,可以随便取,但是这个名字在后面的配置中会有所关联.)然后在mynod ...

  8. jboss 7 启动问题

    19:30:50,176 INFO [org.jboss.modules] JBoss Modules version 1.1.1.GA19:30:50,458 INFO [org.jboss.msc ...

  9. C# GetHashCode与Equals在HashTable表查找时的关系

    using System; using System.Collections.Generic; using System.Text; using Microsoft.Win32; using Syst ...

  10. 获取基于Internet Explorer_Server的聊天窗口内容

    假设在得到窗体中控件的句柄(通过SPY++)的前提下,如果是像文本框这种控件,只要用SendMessage就可得到文本了,但是对于聊天记录窗口却行不通(返回空值),因为那其实是一个内置浏览器Inter ...