Android Thread子线程和主线程的UI交互

本文介绍了在Android开发中,如何在子线程与主线程间进行UI交互的五种方法,包括Activity.runOnUiThread、View.post、View.postDelayed、Handler.post以及Handler.postDelayed。这些方法常用于在网络请求完成后更新UI。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们知道更新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的方法实现,如果有做的不对的地方希望指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值