第八章--更新ui的幾種操作

在文章的開(kāi)頭,大家可以試一下以下的代碼:布局文件就是新建一個(gè)activity的時(shí)候生成的。

public class MainActivity extends AppCompatActivity {

    private TextView mTextView;

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

        mTextView = (TextView) findViewById(R.id.textView);

        new Thread(){
            @Override
            public void run() {
                super.run();
                mTextView.setText("huhu");
            }
        }.start();
    }
}

是不是會(huì)驚奇的發(fā)現(xiàn)在工作線程中更新ui竟然成功了,而且不會(huì)報(bào)錯(cuò)。對(duì),你沒(méi)有看錯(cuò)就是可以。
然而如果這樣寫:先讓線程Thread.sleep()幾秒鐘,就會(huì)報(bào)錯(cuò)。這種情況先是在群里大哥出現(xiàn)了,然后在慕課網(wǎng)里面,專門花了一小節(jié)講了這件事。下面評(píng)論里總結(jié)的比我好,我來(lái)引用一下

更新UI-->會(huì)調(diào)用checkForRelayout()方法
-->invalidate()方法-->invalidate(true)方法,關(guān)注viewParent-->ViewRootImpl是ViewParent的實(shí)現(xiàn)類
--->p.invalidateChild()-->查看ViewRootImpl.invalidateChild()-->checkThread()方法-->判斷UI線程是否是當(dāng)前線程,不相等拋出異常。
ViewRootImpl是onResume()方法才會(huì)創(chuàng)建。所以onCreate()方法中要延遲才可以。
handleResumeActivity()方法--->viewManager.addView()-->ViewRootImpl初始化。關(guān)注viewParent-->ViewRootImpl是ViewParent的實(shí)現(xiàn)類

若看不懂用一句簡(jiǎn)單的話總結(jié)就是:在onResume()才會(huì)去檢查更新UI的線程是不是主線程,所以在onCreate()中啟動(dòng)線程更新UI也許不會(huì)報(bào)錯(cuò)。但是休眠就一定會(huì)。有了這個(gè),我們?cè)匍_(kāi)始講更新UI的操作(工作線程中)。

1、new Handler(Looper.getMainLooper()).post

        new Thread(){
            @Override
            public void run() {
                super.run();
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                       mTextView.setText("ok");
                    }
                });
            }
        }.start();

親測(cè)可以

2、runOnUiThread():在線程中執(zhí)行ui線程

        new Thread(){
            @Override
            public void run() {
                super.run();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mTextView.setText("今天是個(gè)好天氣");
                    }
                });
            }
        }.start();

親測(cè)可以

3、View.post():

        new Thread(){
            @Override
            public void run() {
                super.run();                
                   // Thread.sleep(1000);
                    mTextView.post(new Runnable() {
                        @Override
                        public void run() {
                            mTextView.setText("好像開(kāi)學(xué)了");
                        }
                    });
            }
        }.start();

好像沒(méi)什么變化,以上的我都是寫在onCreate方法中的,但是我先把線程休眠1秒鐘,神奇般的可以更新UI了,或者我把這個(gè)線程寫在onResume()中的時(shí)候又可以用了。
我簡(jiǎn)短的分析一下原因:其實(shí)我也分析不來(lái)什么原因啊,本來(lái)寫了一點(diǎn)但是我是真的說(shuō)不明白,就是深度不夠。簡(jiǎn)單說(shuō)一下,這個(gè)方法必須在onAttachToWindow()之后才執(zhí)行,那這個(gè)方法是在onResume()之后執(zhí)行。否則直接在onCreate()中,而且是在子線程中執(zhí)行的話,則永遠(yuǎn)都不會(huì)執(zhí)行到post里面。附上鏈接供以后拓展view.post()獲取寬高引發(fā)的兩個(gè)思考

4、view.postDelayed():和上面差不多,這個(gè)應(yīng)該就不會(huì)發(fā)生那些問(wèn)題。

5、AsyncTask

class Task extends AsyncTask{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //主線程,首先被執(zhí)行,可以進(jìn)行一些初始化操作。
        }

        @Override
        protected Object doInBackground(Object[] params) {
       //在onPreExecute()后執(zhí)行,運(yùn)行在子線程中
            return null;
        }

        @Override
        protected void onPostExecute(Object o) {
            super.onPostExecute(o);
            //主線程, 在doInBackground()后中執(zhí)行,
        }

        @Override
        protected void onProgressUpdate(Object[] values) {
            super.onProgressUpdate(values);
            //更新progress操作

        }
    }

先就這樣。。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容