访问网络需要添加访问网络的权限。
Android not responding(应用程序无响应)阻塞了主线程 ANR异常
Android4.0以后的版本,只要发现请求网络的操作,都不允许放到主线程中。若放到主线程中会报异常。防止阻塞主线程。所以请求网络的操作要放到子线程中。
异常:
CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
只有原始的线程(主线程, ui线程)才能修改view对象.
在子线程中修改view的显示状态, 会报上面异常.
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = "MainActivity";
private ImageView iv;
private EditText et;
private HttpURLConnection conn;
private final int SUCCESS = 0;
private final int ERROR = 1;
private Handler handler = new Handler() {
/**
* 接收消息
*/
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i(TAG, "what=" + msg.what);
if (msg.what == SUCCESS) {
iv.setImageBitmap((Bitmap) msg.obj);// 设置ImageView显示的图片
} else if (msg.what == ERROR) {
Toast.makeText(MainActivity.this, "抓取失败!", 0).show();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
et = (EditText) findViewById(R.id.et);
findViewById(R.id.btn).setOnClickListener(this);
}
@Override
public void onClick(View v) {
final String url = et.getText().toString();
new Thread(new Runnable() {
@Override
public void run() {
Bitmap bitmap = getImageFromNet(url);
if (bitmap != null) {
Message msg = new Message();
msg.what = SUCCESS;
msg.obj = bitmap;
handler.sendMessage(msg);
} else {
Message msg = new Message();
msg.what = ERROR;
handler.sendMessage(msg);
}
}
}).start();
}
/**
* 根据url到网络获取图片
*
* @param url
* @return
*/
private Bitmap getImageFromNet(String url) {
try {
URL myUrl = new URL(url);// 创建一个URL对象
// 得到HTTP的连接对象
conn = (HttpURLConnection) myUrl.openConnection();
conn.setRequestMethod("GET");// 设置请求方法为get
conn.setConnectTimeout(10 * 1000);// 设置连接服务器的超时时间,如果超时没有连接成功,会抛异常
conn.setReadTimeout(5 * 1000);// 设置读取数据时的超时时间,如果超时没有成功,抛异常
conn.connect();// 开始连接
int code = conn.getResponseCode();// 得到服务器的响应码
if (code == 200) {
// 访问成功
InputStream is = conn.getInputStream();// 获得服务器返回的数据流
Bitmap bitmap = BitmapFactory.decodeStream(is);// 根据流数据创建一个bitmap位图对象
return bitmap;
} else {
Log.i(TAG, "访问失败!访问码为:" + code);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.disconnect();// 关闭连接
}
}
return null;
}
}
除了Handler方法外,在子线程中调用runOnUiThread();方法,也可以实现程序在主线程中执行。比如在子线程中想要弹出吐司,就可以用该方法。
// 执行任务在主线程中
runOnUiThread(new Runnable() {
@Override
public void run() {
// 就是在主线程中操作
Toast.makeText(MainActivity.this, "操作成功!", 0).show();
}
});