您的位置:首页 > 移动开发 > Android开发

【移动开发】Android中异步加载数据(一)Handler + Thread

2013-07-18 15:40 671 查看
在我们开发当中很多时候都会遇到:从网络上获取数据的操作或大量的IO数据操作时,会耗费很长时间,为了使用户的体验效果更好,现在大多数开发者都会使用异步的方式去处理这些的操作,异步的方式有好多种,在此我汇总了以下两种:

1.Handler + Thread的方式
2.AsyncTask异步更新UI界面
这两种方式各自有各自的优缺点,这里先介绍一下第一种方式

1.Hanlder介绍:
官方文档:

A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
一个处理程序允许你发送和处理消息或者Runnable对象关联到的一个线程的MessageQueue。每个处理程序的实例相关联着一个单个线程和一个线程的消息队列。当你创建一个新的处理程序,它被绑定到线程/消息队列的线程时创建它——从那时起,它将提供消息和runnables给消息队列和执行他们出来的消息队列。
Handler主要方法:

常用方法解释
Message obtainMessage(int what, Object obj)获取一个Message对象,包含了一个标识和value
boolean post(Runnable r)将Runnable r添加到消息队列,之后会被UI线程执行
boolean postDelayed(Runnable r, long delayMillis)延迟多少毫秒之后,再将该线程加入到消息队列中
boolean sendEmptyMessage(int what)发送一个只有标识的消息
boolean sendMessage(Message msg)添加一条消息到消息队列的末尾
void handleMessage(Message msg)用于处理接收到的消息
简单的说Android采用UI单线程模型,所以只能在主线程中对UI元素进行操作。如果在非UI线程直接对UI进行了操作,就会报错,当然为了提高效率,Android为我们提供了消息循环的机制,我们可以利用这个机制来实现线程间的通信,在非UI线程发送消息到UI线程,最终让Ui线程来进行ui的操作

2.在非UI线程中发送消息通知UI线程更新界面:


import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
/**
* Handler + Thread 实现异步加载图片
* @author ZHF
*
*/
public class MainActivity extends Activity {
private static final int MSG_SUCCESS = 0;//成功获取图片
private static final int MSG_FAILURE = 1;//获取图片失败
public static final String IMG_URL = "http://images.51cto.com/images/index/Images/Logo.gi";

Button btn_handler;
ImageView imageView;

private DownloadImgThread downloadImgThread;

private Handler mHandler = new Handler(){
public void handleMessage(Message msg) { //该方法是在UI主线程中执行
switch(msg.what) {
case MSG_SUCCESS:
imageView.setImageBitmap((Bitmap)msg.obj);  //显示图片
break;
case MSG_FAILURE:
Toast.makeText(MainActivity.this, "获取图片失败", Toast.LENGTH_LONG);
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

imageView = (ImageView) this.findViewById(R.id.imageView);

btn_handler = (Button) this.findViewById(R.id.btn_handler);
btn_handler.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//开启一个非UI线程,用于下载图片
downloadImgThread = new DownloadImgThread();
downloadImgThread.start();
}
});
}

/**图片下载线程**/
private class DownloadImgThread extends Thread{
HttpURLConnection conn;
InputStream inputStream;
Bitmap imgBitmap;

@Override
public void run() {
try {
URL url = new URL(IMG_URL);
if(url != null) {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(2000);
connection.setDoInput(true);
connection.setRequestMethod("GET");
int code = connection.getResponseCode();
if(200 == code) {
inputStream = connection.getInputStream();
imgBitmap = BitmapFactory.decodeStream(inputStream);
//获取图片成功,向ui线程发送MSG_SUCCESS标识和bitmap对象
mHandler.obtainMessage(MSG_SUCCESS,imgBitmap).sendToTarget();
}else {
//获取图片失败,向ui线程发送MSG_FAILURE
mHandler.obtainMessage(MSG_FAILURE).sendToTarget();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

}
在自己的线程中获取到imgBitmap,不能直接imageView.setImageBitmap(imgBitmap),会报错的哦! 通过Message中obj将其存储起来,传递到UI线程中再对其操作。
权限:

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


2.View的post(Runnable r)方法
在获取到imgBitmap之后,可以通过下面代码实现UI界面的更新哦:


//另外一种更简洁的发送消息给ui线程的方法。
mImageView.post(new Runnable() {
@Override
public void run() {//run()方法会在ui线程执行
mImageView.setImageBitmap(bm);
}
});
这是为什么那?
因为Android框架为每个应用的主线程创建了一个隐式的handler,使用post方法的原理就是给这个隐式的handler发送一个Runnable对象,然后隐式的handler会在ui线程执行Runnable对象的run()方法。

下一篇(AsyncTask):http://smallwoniu.blog.51cto.com/3911954/1252156

附件:http://down.51cto.com/data/2363167
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐