我们知道更新UI只能在主线程中,但是在日常应用中我们除了使用封装好的AsyncTask外大多会使用Thread+Handler的手法来实现子线程从网络获取数据,然后再修改主线程上的View视图,现在我们可以使用下面5种方法来实现线程间的UI交互.
1,认识Activity.runOnUiThread(Runnable)先上代码
public class MyActivity extends Activity {
private final static String PIC_URL =
"http://www.easyicon.net/api/resizeApi.php?id=1171895&size=128";
private ImageView picIv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
picIv = (ImageView) findViewById(R.id.pic_iv);
}
/**
* 获取图片的监听事件,此方法需要和xml布局中的button的 android:onClick="doRequest"
* 属性名称一致并且为public类型不然会报一些问题
* @param view
*/
publicvoid doRequest(View view) {
thread.start();
}
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
final Bitmap bitmap = getBitmap(PIC_URL);
if (bitmap != null){
MyActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
picIv.setImageBitmap(bitmap);
}
});
}
}
});
/**
* 获取网络资源图片
* @param path 图片地址
* @return bitmap
*/
public static Bitmap getBitmap(String path) {
InputStream is = null;
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setRequestMethod("GET");
is = conn.getInputStream();
if (conn.getResponseCode() == 200) {
Bitmap bitmap = BitmapFactory.decodeStream(is);
conn.disconnect();
return bitmap;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
其中main.xml 的布局为
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="doRequest"
android:text="获取图片"/>
<ImageView
android:id="@+id/pic_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"/>
</LinearLayout>
AndroidManifest.xml添加权限:
<uses-permission android:name="android.permission.INTERNET"/>
2,了解View.post(Runnable)将MyActivity.this.runOnUiThread方法替换为
picIv.post(new Runnable() {
@Override
public void run() {
picIv.setImageBitmap(bitmap);
}
});
3,使用View.postDelayed(Runnable, long)实现线程间的UI交互将上述方法改为
picIv.postDelayed(new Runnable() {
@Override
public void run() {
picIv.setImageBitmap(bitmap);
}
},1*1000);//1*1000表示1s
4,学会Handler.post(Runnable)实现线程间的UI交互将上述方法改为
new Handler().post(new Runnable() {
@Override
public void run() {
picIv.setImageBitmap(bitmap);
}
});
但由于我们是在子线程内部new的Handler所以会报这个异常:
java.lang.RuntimeException:
Can't create handler inside thread that has not called Looper.prepare()
所以我们在线程外获取Handler对象即可Handler handler = new Handler();
然后改成下面的形式就哦了。
handler.post(new Runnable() {
@Override
public void run() {
picIv.setImageBitmap(bitmap);
}
});
5,最后使用Handler.postDelayed(Runnable, long)实现线程间的UI交互将上述方法改为
handler.postDelayed(new Runnable() {
@Override
public void run() {
picIv.setImageBitmap(bitmap);
}
},1*1000);
以上就是总结的5种方法在android子线程中更新UI的方法实现,如果有做的不对的地方希望指正