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
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();
}
}
サブスレッドで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
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(MainActivity.this , "1111" , Toast.LENGTH_SHORT).show();
Looper.loop();
}
}).start();