Androidテクノロジー----Activityソース

2773 ワード

一、Activity関連


なぜ下は眠らずにsetText()を設定し、睡眠を1秒追加すると異常を放出するのですか?次のコードを見てください.
public class MainActivity extends AppCompatActivity {

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

        final TextView textview = (TextView) findViewById(R.id.textview);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                textview.setText("1111");

            }
        }).start();
    }
}

上記コード:スリープを追加しない場合は、スレッドにsetText(「1111」)を直接設定してもエラーは報告されません.睡眠を追加するとsetText(「1111」)を設定すると1秒後にエラーが発生します:Only the original thread that created a view hierarchy can touch its views.元のスレッド以外のスレッドでUIを更新することはできません
前提知識:ViewRootImplでは、まずrequestLayout()を呼び出し、次にrequestLayout()でcheckThread()メソッドを呼び出します.このメソッドは、現在のスレッドが作成したスレッドに等しいかどうかを判断し、等しくなければ、異常を直接放出します.
理由は以下のとおりです:1>:睡眠を追加しない:エラーを報告しないのは、onCreate()はMainActivityの作成後に実行され、checkThread()はViewRootImplのrequestLayout()で実行され、レイアウトの描画プロセスはonResume()の後に開始されます.だから、onCreate()でnew Thread(new Runnable()).start()UIの更新は可能です.onResume()は呼び出されず、レイアウトは描画されませんので、checkThread()メソッドは呼び出されませんので、例外は放出されません.
2>:睡眠を追加:しかし、睡眠1秒後、この時点でonResume()が実行され、レイアウトの描画が開始され、UIを更新するとrequestLayout()が呼び出され、checkThread()メソッドが呼び出されるため、異常が放出されます.

二.プライマリ・スレッド(UIスレッド)、サブスレッドとは?


サブスレッドでUIを更新できないという観点はよくありません.サブスレッドがUIを更新できると仮定すると、エラーの問題が発生します.同期の問題があるため、スレッド1とスレッド2が同時にUIを更新すると仮定すると、スレッド1に更新されるか、スレッド2に更新されるかを確保できません.ロックしますか?ロックの場所を特定できません.だからグーグルは1つのスレッドでUIを更新することを許可するしかなく、このスレッドをUIスレッドと呼び、メインスレッドとも呼ばれています.
だから、グーグルはこのようにしてサブスレッドでUIを更新すると、Only the original thread that created a view hierarchy can touch its viewsを間違えます.サブスレッドでUIを更新できないのではなく、元のスレッド以外のスレッドでUIを更新することはできません.

三.toastのnew Threadでの質問:

new Thread(new Runnable() {
            @Override
            public void run() {
               
                Looper.prepare();
                Toast.makeText(MainActivity.this , "1111" , Toast.LENGTH_SHORT).show();
                Looper.loop();

            }
        }).start();

toastを直接new Thread()にポップアップすると、エラーが表示されます.エラーが表示されます.Can't create handler inside thread that has not called Looperprepare()
Looperを追加した場合prepare()とLooper.loop()は、toastをポップアップすることができます.これはサブスレッドでポップアップされたtoastです.
サブスレッドでtoastをポップアップできます.なぜなら、サブスレッド更新ToastはWindowManagerにロードされているためActivityではないので、ViewRootImplには来ないのでcheckThread()は実行されないので、例外は放出されません.
感謝:
https://www.jianshu.com/p/0da229c00f0d