子线程不能修改UI|SquirrelNote

作者: 跳动的松鼠 | 来源:发表于2017-11-08 15:57 被阅读18次

异常信息:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
必须在程序的主线程(UI)中更新界面显示

如下代码:

public class BActivity extends Activity {

    private Button mBtn1_bpage;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);

        //初始化控件
        mBtn1_bpage = (Button) findViewById(R.id.btn1_bpage);
        mTextView = (TextView) findViewById(R.id.tv1_bpage);

        //设置监听
        mBtn1_bpage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                changeText();
            }
        });

    }

    /**
     * 改变文本
     */
    private void changeText() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                mTextView.setText("标题!");
            }
        }).start();
    }
}

运行,程序崩溃。

有时会碰到在非主线程更新视图的需要,有两种处理的方式,一种是Handler,另一种是Activity中的runOnUiThread(Runnable)方法。

方法1:使用Handler

public class BActivity extends Activity {

    private Button   mBtn1_bpage;
    private TextView mTextView;

    Handler mHandler = new Handler() {
        //接受子线程的消息机制
        @Override
        public void handleMessage(Message msg) {
            int what=msg.what;

            switch (what){
                case 102:
                    //改变页面的文字
                    mTextView.setText("改变文字");
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);

        //初始化控件
        mBtn1_bpage = (Button) findViewById(R.id.btn1_bpage);
        mTextView = (TextView) findViewById(R.id.tv1_bpage);

        //设置监听
        mBtn1_bpage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                changeText();
            }
        });

    }

    /**
     * 改变文本
     */
    private void changeText() {
        new Thread(new Runnable() {
            @Override
            public void run() {
//                mTextView.setText("标题!");
                mHandler.sendEmptyMessage(102);
            }
        }).start();
    }
}

方法2:使用runOnUiThread(Runnable)方法

//设置监听
mBtn1_bpage.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
//                changeText();
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //改变页面的文字
                mTextView.setText("改变文字2");
            }
        });
    }
});

方法3:使用AsyncTask

public class BActivity extends Activity {

    private Button   mBtn1_bpage;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);

        //初始化控件
        mBtn1_bpage = (Button) findViewById(R.id.btn1_bpage);
        mTextView = (TextView) findViewById(R.id.tv1_bpage);

        //设置监听
        mBtn1_bpage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MyAsyncTask myAsyncTask=new MyAsyncTask();
                myAsyncTask.execute();
            }
        });

    }

    private class MyAsyncTask extends AsyncTask<Void,Void,Void>{

        @Override
        protected Void doInBackground(Void... params) {
            publishProgress();
            return null;
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);

            //改变页面的文字
            mTextView.setText("改变文字3");
        }

        @Override
        protected void onPostExecute(Void result) {

            //改变页面的文字
            mTextView.setText("改变文字3_2");
            super.onPostExecute(result);
        }
    }

三个方法:

  • onProgressUpdate方法的执行在收到publishProgress方法调用后,运行在UI线程中,对UI控件进行处理。
  • onPostExecute()方法,则在doInBackground()方法结束后运行在UI线程,对result进行处理
  • doInBackground()方法中,就是在后台线程中处理异步任务,不能做Toast操作,否则出现异常。

以上是根据我的一些理解,做的总结分享,旨在抛砖引玉,希望有更多的志同道合的朋友一起讨论学习,共同进步!

相关文章

  • 子线程不能修改UI|SquirrelNote

    异常信息: android.view.ViewRootImpl$CalledFromWrongThreadExce...

  • Android下的消息机制

    Android下的消息机制 子线程不可以修改UI 只有主线程才可以修改UI 如果子线程想要更新UI就必须利用消息机...

  • Handler消息机制

    Android规定只允许UI线程修改Activity里面的UI组件,如果我们要在子线程中去执行更改UI的操作,会导...

  • Android中为什么在子线程不能更新UI

    Android有条铁则:子线程不能修改UI 至于为什么 ,就是修改了会报错呗 具体错误如下 但是令人称奇的是:如果...

  • 多线程

    不能再非主线程中修改UI控件属性,不建议在主线程中做耗时操作 UI线程:主线程Activity Thread Me...

  • 如何做到在子线程更新 UI?

    一般来讲,子线程是不能更新 UI 的,如果在子线程更新 UI,会报错。 但在某种情况下直接开启线程更新 UI 是不...

  • iOS子线程操作UI

    首先声明一点:子线程里面是可以更新UI的。 之所以说子线程不能操作UI是因为UIKit不是线程安全的。UI操作涉及...

  • 自线程绘制UI & equals和hashcode方法

    1.为什么不能在子线程做UI绘制 简单的说,ViewRootImpl对象生成之后,就不能在子线程操作UI,某些可以...

  • Android多线程

    1.沿用java的子线程创建 2.在子线程中不能更新UI,那么在Android中更新UI的方法 runOnUiTh...

  • 理解JS 线程,和Android线程

    1,Android开发都知道,UI线程,和子线程; UI线程:可以操作ui界面, 子线程:不可以操作ui界面 2,...

网友评论

    本文标题:子线程不能修改UI|SquirrelNote

    本文链接:https://www.haomeiwen.com/subject/sitymxtx.html