使用handler的步骤:
1.在主线程中创建handler成员变量;
2.在子线程中得到handler,调用sendMessage方法,给主线程发送一个消息,说我要修改UI界面;
3.handler经过主线程的授权后,修改UI界面;
handler的工作原理(handler/message/looper三者之间的关系):
补充前提知识:所有使用UI界面的操作系统,后台都运行着一个死循环(Looper),它在不停的监听和接收用户发出的指令,一旦接收到指令就会立即执行;
在应用程序已启动的时候,系统就给它提供了死循环(Looper);当子线程需要发送消息(修改UI界面),就会调用handler的sendMessage方法给主线程发送一个消息(Message),handler会把消息放到looper中的消息队列(MessageQueue)中;在Looper中还有一个死循环,这个死循环在不停的从消息队列中读取消息,取到消息后分发给handler,handler在调用handleMessage方法修改UI界面;
代码:
package com.itheima.picview;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et_path;
private ImageView iv_image;
//1.在主线程中创建handler成员变量;
private Handler handler = new Handler(){
/**
* 接收和处理消息
*/
public void handleMessage(Message msg) {
// 接收消息
Bitmap bitmap = (Bitmap) msg.obj;
// 处理消息:修改UI界面
iv_image.setImageBitmap(bitmap);
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1.找到控件对象
et_path = (EditText) findViewById(R.id.et_path);
iv_image = (ImageView) findViewById(R.id.iv_image);
}
/**
* 查看网络上的一张图片
* @param view
*/
public void viewPic(View view){
// 2.从输入框中得到用户输入的图片网络路径
final String path = et_path.getText().toString().trim();
if(TextUtils.isEmpty(path)){
Toast.makeText(this, "请输入图片的网络路径", 0).show();
return;
}else{
// 把访问网络的代码写在子线程中;
new Thread(){
public void run() {
try {
// 3.访问网络,从网络上获得图片的数据,显示在imageview上
// 3.1.创建URL对象,打开一个http类型的连接;
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 3.2.给连接设置请求参数:请求方式(GET,POST),连接的超时时间,请求方式必须大小;
conn.setRequestMethod("GET"); // ,默认使用GET方式
conn.setConnectTimeout(3000); //超时时间为3000毫秒
// 设置其他参数
// conn.setRequestProperty("Accept-Language", "zh-CN");
// 3.3.服务器给客户端返回数据:响应码为200 客户端正常发送请求,服务器端返回数据成功,404 找不到数据资源,503 服务器内部错误;
// 首先判断服务器返回的响应码是不是200.服务器端是以二进制流的形式返回数据的;然后接收二进制流的数据.
// 得到服务器端返回的响应码
int code = conn.getResponseCode();
if(code == 200){ // 服务器端返回数据成功
// 接受服务器端返回的二进制输入流
InputStream is = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(is);
// 2.在子线程中得到handler,调用sendMessage方法,给主线程发送一个消息,说我要修改UI界面;
// 创建一个消息对象:消息盒子
Message msg =new Message();
msg.obj = bitmap;
handler.sendMessage(msg);
}
// 3.4.添加访问互联网的权限;
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
}
}
02_消息处理常用另一个API
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_result.setText(result);
}
});