异步消息处理机制
主线程又被称为UI线程,Android是不允许在子线程中进行UI操作的。在主线程中进行耗时操作,程序易发生ANR错误(Application Not Response)。我们必须在子线程中执行一些耗时操作,然后根据任务的执行结果来更新相应的UI控件,这就用到了异步消息处理机制。
代码实现:
public class MainActivity extends Activity {
private static final int IMAGE = 0;
private static final int TOAST = 1;
static ImageView iv ;
static MainActivity ma;
//Handler对象设置成static,内部变量都需要是静态static
static Handler handler = new Handler(){
//此方法在主线程中调用,可以用来刷新UI
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case IMAGE:
//把位图对象显示至ImageView
iv.setImageBitmap((Bitmap) msg.obj);
break;
case TOAST:
Toast.makeText(ma, "请求失败", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
ma = this;
}
/**
* 下载图片
*/
public void click(View v){
//创建一个子线程,在子线程中处理网络请求
new Thread(){
@Override
public void run() {
//确定网址
String path = "http://192.168.1.100:8080/home_gradient.jpg";
try {
//将网址封装成一个Url对象
URL url = new URL(path);
//获取客户端和服务器的连接对象,此时还没有建立连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//对连接对象进行初始化
connection.setRequestMethod("GET"); //设置请求方法
connection.setConnectTimeout(5000); //设置连接超时
//发送请求,与服务器建立连接
connection.connect();
if (connection.getResponseCode() == 200) { //如果响应吗为200,说明请求成功
//获取服务器中响应头中的流,流里的数据就是客户端请求的数据
InputStream is = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(is);
//使用Handler对象的obtainMessage方法获取一个消息对象Message
Message message = handler.obtainMessage();
//消息对象可以携带数据
message.obj = bitmap;
message.what = IMAGE;
//把消息发送至主线程的消息队列
handler.sendMessage(message);
}
else {
//弹出吐司也是一种UI的刷新,需要在主线程中运行
Message message = handler.obtainMessage();
message.what = TOAST;
handler.sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(connection != null){
//关闭HTTP连接
connection.disconnect();
}
}
}
}.start(); //开启线程任务
}
}
解析异步消息处理机制
异步消息处理主要由四部分组成:Message
、Handler
、MessageQueue
和Looper
**Message: **
Message
对象是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同的线程之间交换数据。what
、arg1
、arg2
字段携带一些整型数据,obj
字段携带一个object
对象Handler:
Handler
对象主要用于发送和处理消息。发送消息一般是使用sendMessage()
方法,消息被发送到消息队列(MessageQueue)中,轮询器(Looper)会把消息对象传递给消息处理器(Handler),消息处理器调用handleMessage()
方法,此方法运行在主线程中,可以刷新UIMessageQueue:
MessageQueue
对象是消息队列的意思,主要存放所有通过Handler
发送的消息。这部分消息会一直存放在消息队列里,直至被轮询器取出传递给消息处理器。每个线程中只会有一个消息队列对象Looper:
Looper
是轮询器的意思,是每个线程中的消息队列MessageQueue
的管家,其会不停的检测消息队列中是否有消息对象,若有将从消息队列中取出消息对象传递给消息处理器