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

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/w_jingjing0428/article/details/52416709

在文章的開頭,大家可以試一下以下的代碼:佈局文件就是新建一個activity的時候生成的。

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();
    }
}

是不是會驚奇的發現在工作線程中更新ui竟然成功了,而且不會報錯。對,你沒有看錯就是可以。
然而如果這樣寫:先讓線程Thread.sleep()幾秒鐘,就會報錯。這種情況先是在羣裏大哥出現了,然後在慕課網裏面,專門花了一小節講了這件事。下面評論裏總結的比我好,我來引用一下

更新UI–>會調用checkForRelayout()方法
–>invalidate()方法–>invalidate(true)方法,關注viewParent–>ViewRootImpl是ViewParent的實現類
—>p.invalidateChild()–>查看ViewRootImpl.invalidateChild()–>checkThread()方法–>判斷UI線程是否是當前線程,不相等拋出異常。
ViewRootImpl是onResume()方法纔會創建。所以onCreate()方法中要延遲纔可以。
handleResumeActivity()方法—>viewManager.addView()–>ViewRootImpl初始化。關注viewParent–>ViewRootImpl是ViewParent的實現類

若看不懂用一句簡單的話總結就是:在onResume()纔會去檢查更新UI的線程是不是主線程,所以在onCreate()中啓動線程更新UI也許不會報錯。但是休眠就一定會。有了這個,我們再開始講更新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();

親測可以

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

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

親測可以

3、View.post():

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

好像沒什麼變化,以上的我都是寫在onCreate方法中的,但是我先把線程休眠1秒鐘,神奇般的可以更新UI了,或者我把這個線程寫在onResume()中的時候又可以用了。
我簡短的分析一下原因:其實我也分析不來什麼原因啊,本來寫了一點但是我是真的說不明白,就是深度不夠。簡單說一下,這個方法必須在onAttachToWindow()之後才執行,那這個方法是在onResume()之後執行。否則直接在onCreate()中,而且是在子線程中執行的話,則永遠都不會執行到post裏面。附上鍊接供以後拓展view.post()獲取寬高引發的兩個思考

4、view.postDelayed():和上面差不多,這個應該就不會發生那些問題。

5、AsyncTask

class Task extends AsyncTask{

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

        @Override
        protected Object doInBackground(Object[] params) {
       //在onPreExecute()後執行,運行在子線程中
            return null;
        }

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

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

        }
    }

先就這樣。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章