安卓-子线程中更新UI的几种常见方法

安卓的子线程中不允许直接更新UI,否则会报错。一般常见的子线程中更新UI的几种方法如下:

1)runOnUiThread

2)Handler与Message

3)View.post(Runnable )

4)AsyncTask

下面写个demo测试下几种情况,在布局文件中定义5个按钮和一个文本控件,5个按钮中的前4个用于演示前面提到的可以进行更新UI的四种情况,第5个按钮测试在子线程中直接更新UI报错的问题,文本控件用来测试被更新的控件,不同的更新显示不同的内容。

先看下界面的效果图(不知道能否正常显示):


第5个按钮测试崩溃情况输出错误如下:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

下面展示下测试代码:

布局文件activity_update_ui.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_update_ui"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.mobile.cdtx.blog.main.activity.UpdateUIActivity">

    <Button
        android:id="@+id/id_btn_one"
        android:textAllCaps="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="runOnUiThread"/>

    <Button
        android:id="@+id/id_btn_two"
        android:textAllCaps="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Handler与Message"/>

    <Button
        android:id="@+id/id_btn_three"
        android:textAllCaps="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="View.post(Runnable )"/>

    <Button
        android:id="@+id/id_btn_four"
        android:textAllCaps="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="AsyncTask"/>

    <Button
        android:id="@+id/id_btn_five"
        android:textAllCaps="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Crash"/>

   <TextView
       android:id="@+id/id_tv_text"
       android:textAllCaps="false"
       android:layout_marginTop="10dp"
       android:background="#F32567"
       android:gravity="center"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="wait for update"/>

</LinearLayout>

主界面测试代码:

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.mobile.cdtx.blog.R;

public class UpdateUIActivity extends AppCompatActivity implements View.OnClickListener{
    private static final String TAG = "UpdateUIActivity";
    private static int MESSAGE_WHAT = 1;
    Button btnOne,btnTwo,btnThree,btnFour,btnFive;
    TextView tvText;
    private Handler handler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_update_ui);

        initView();//初始化控件

        handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if(msg.what == MESSAGE_WHAT){
                    tvText.setText("Handler and Message");
                }
            }
        };
    }

    //初始化控件
    private void initView(){
        btnOne = (Button)findViewById(R.id.id_btn_one);
        btnTwo = (Button)findViewById(R.id.id_btn_two);
        btnThree = (Button)findViewById(R.id.id_btn_three);
        btnFour = (Button)findViewById(R.id.id_btn_four);
        btnFive = (Button)findViewById(R.id.id_btn_five);
        tvText = (TextView)findViewById(R.id.id_tv_text);
        btnOne.setOnClickListener(this);
        btnTwo.setOnClickListener(this);
        btnThree.setOnClickListener(this);
        btnFour.setOnClickListener(this);
        btnFive.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
         switch(v.getId()){
             case R.id.id_btn_one://runOnUiThread
                 testOne();
                 break;
             case R.id.id_btn_two://Handler与Message
                 textTwo();
                 break;
             case R.id.id_btn_three://View.post(Runnable )
                 textThree();
                 break;
             case R.id.id_btn_four://AsyncTask
                 testFour();
                 break;
             case R.id.id_btn_five://Crash
                 textFive();
                 break;
             default:
                 break;
         }
    }

    //runOnUiThread
    private void testOne(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tvText.setText("runOnUiThread");
                    }
                });
            }
        }).start();
    }

    //Handler与Message
    private void textTwo(){
       new Thread(new Runnable() {
           @Override
           public void run() {
               Message message = new Message();
               message.what = MESSAGE_WHAT;
               handler.sendMessage(message);
           }
       }).start();
    }

    //View.post(Runnable )
    private void textThree(){
         new Thread(new Runnable() {
             @Override
             public void run() {
                 try {
                     Thread.sleep(2000);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
                 btnThree.post(new Runnable() {
                     @Override
                     public void run() {
                         tvText.setText("View.post(Runnable )");
                     }
                 });
             }
         }).start();
    }

    //AsyncTask
    private void testFour(){
        MyAsyncTask myAsyncTask = new MyAsyncTask(tvText);
        myAsyncTask.execute();
    }

    //Crash-主要用于演示如果在子线程中如果直接更新UI会崩溃
    private void textFive(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                tvText.setText("Crash");
            }
        }).start();
    }

    //自定义AsyncTask类
    class MyAsyncTask extends AsyncTask<Void,Integer,String>{
        TextView textView;
         public MyAsyncTask(TextView textView){
             this.textView = textView;
         }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            textView.setText("开始准备执行doInBackground");
        }

        @Override
        protected String doInBackground(Void... params) {
            try{
                Log.i(TAG, "doInBackground: 这里可以做耗时运算");
                Thread.sleep(2000);
            }catch (Exception e){
                e.printStackTrace();
            }
            return "AsyncTask";
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            textView.setText(s);
        }
    }
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值