私は興味深い問題に直面しました。onCreate/onStart/onResume
アクティビティのメソッドで次のコードを記述した場合:
final Button myButton = (Button)findViewById(R.id.myButton);
final TextView myTextView = (TextView)findViewById(R.id.myTextView);
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
myTextView.setText("Hello text");
}
});
myButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
thread.start();
}
});
また:
final TextView myTextView = (TextView)findViewById(R.id.myTextView);
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.currentThread().sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
myTextView.setText("Hello text");
}
});
thread.start();
どうあるべきか、エラーがスローされます
android.view.ViewRoot $ CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views."
この場合、ui-threadでビューを更新する必要があることは明らかです。 (Handler, AsyncTask, runOnUiThread, view.post).
ただし、別のスレッドでビューを遅滞なく(スリープ呼び出しなしで、またはボタンを押してスレッドを開始せずに)更新した場合、例外はスローされません。
final TextView myTextView = (TextView)findViewById(R.id.myTextView);
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
myTextView.setText("Hello text");
}
});
thread.start();
なぜそのような行動があるのか誰か教えてもらえますか?
アップデート:
私はAndroidのソースコードを学び、次の結論に達しました。ナンディーシュは真実を書いた。ビューのdispatchAttachedToWindow(AttachInfo info、int visible)メソッドと呼ばれるビューを初期化する場合。これにより、mAttachInfoフィールドが初期化されます。mAttachInfoオブジェクトにはmViewRootImplフィールドがあります。nullの場合、getViewRootImplはnullとして返されます。
public ViewRootImpl getViewRootImpl() {
if (mAttachInfo != null) {
return mAttachInfo.mViewRootImpl;
}
return null;
}
ViewRootImplにはcheckThreadメソッドが含まれています。スレッドを比較します。ビューを作成したスレッドと、ビューの更新要求のスレッドです。
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
したがって、ビューが初期化されていない場合、チェックは行われず、変更によって例外がスローされることはありません。