Handler消息传输机制是基于一句话:在哪个线程中创建的视图,那么就只能在哪个线程中去更改界面(一般是主线程即UI线程)。
本文通过子线程去获取网络中的某张图片,借此熟悉Handler的使用。
activity_main.xml文件如下:
<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"
tools:context=".MainActivity" >
<EditText
android:id="@+id/ed_path"
android:text="http://www.itheima.com/images_new/logo.jpg"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button
android:text="获取图片"
android:onClick="gogetImage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ImageView
android:id="@+id/iv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
AndroidManifest.xml中添加联网权限:
<uses-permission android:name="android.permission.INTERNET"/>
MainActivity.class代码如下:
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
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 {
protected static final int SUCCESS = 0;
protected static final int NETWORK_ERROR = 1;
protected static final int ERROR = 2;
private EditText ed_path;
private ImageView iv;
private String path;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed_path = (EditText) findViewById(R.id.ed_path);
iv = (ImageView) findViewById(R.id.iv);
}
public void gogetImage(View v){
path = ed_path.getText().toString().trim();
if(TextUtils.isEmpty(path)){
Toast.makeText(this, "路径有错误...", 0).show();
return;
}
new Thread(){
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//连接网络的时候, 有很多 不确定性...
// 为了提供用户的感受, 会 设置一个 连接 超时的 时间
conn.setConnectTimeout(5000);
//设置请求的方式
conn.setRequestMethod("GET");
//拿到返回的数据的类型
String contentType = conn.getContentType();
//数据的长度
int length = conn.getContentLength();
System.out.println("contentType :" + contentType);
System.out.println("length :" + length);
// 获得服务器返回的状态吗, 根据状态码判断是否成功
int code = conn.getResponseCode();
if(code==200){
//进来则表示成功的处理了请求, 返回了数据
// 获得返回的图片的流数据
InputStream in = conn.getInputStream();
//可以通过API将一个流数据转换为一个图片
Bitmap bitmap = BitmapFactory.decodeStream(in);
// iv.setImageBitmap(bitmap);
//子线程中通过handler去发一个消息出去
// Message msg = new Message();
Message msg = Message.obtain();
msg.what=SUCCESS;
msg.obj = bitmap;
//放到了消息队列, messageQuerue中,由循环器looper 去取出消息 ,然后 再通知handler去处理
mHandler.sendMessage(msg);
in.close();
}else{
//通知 ui 去给用户一个友好的提示
Message msg = Message.obtain();
msg.what=ERROR;
mHandler.sendMessage(msg);
}
//这里要连接网络,所以需要去申请连接网络的权限
} catch (Exception e) {
//通知 ui 去给用户一个友好的提示
//Toast其实也在更新 ui , 更新ui 是不能放在子线程中去做的
// Toast.makeText(MainActivity.this, "连接错误 ....", 0).show();
Message message = Message.obtain();
message.what= NETWORK_ERROR;
mHandler.sendMessage(message);
e.printStackTrace();
}
};
}.start();
// 连接网络的api URL类
}
//声明一个handler实例,实现 handleMessage() 方法
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case SUCCESS:
//取出消息中的数据
Bitmap bitmap = (Bitmap) msg.obj;
iv.setImageBitmap(bitmap);
break;
case NETWORK_ERROR:
//弹出错误提示消息
System.out.println("====== NETWORK_ERROR");
Toast.makeText(MainActivity.this, "连接错误 ....", 0).show();
break;
case ERROR:
//弹出友好提示消息
System.out.println("====== ERROR");
Toast.makeText(MainActivity.this, " 获得资源失败 ....", 0).show();
break;
default:
break;
}
};
};
}