子线程不能修改UI|SquirrelNote

异常信息:

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{

        @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)