在我们开发当中很多时候都会遇到:从网络上获取数据的操作或大量的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://p_w_picpaths.51cto.com/p_w_picpaths/index/Images/Logo.gi";
Button btn_handler;
ImageView p_w_picpathView;
private DownloadImgThread downloadImgThread;
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) { //该方法是在UI主线程中执行
switch(msg.what) {
case MSG_SUCCESS:
p_w_picpathView.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);
p_w_picpathView = (ImageView) this.findViewById(R.id.p_w_picpathView);
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,不能直接p_w_picpathView.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
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。