对于下面的示例代码,它尝试从非ui线程更新UI,这在Android 4.x上崩溃但在Android 8上运行良好(这让我感到惊讶!)。
public class TestActivity extends AppCompatActivity {
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
mTextView = findViewById(R.id.test_text);
}
@Override
protected void onResume() {
super.onResume();
test2();
}
private void test2() {
mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Util.log("AAA thread name " + Thread.currentThread().getName());
mTextView.setText("AAA");
}
}.start();
}
});
}
}
想知道Android 8上的哪些更改使其有效。
编辑:在Android 4上崩溃的堆栈跟踪:
09-08 00:08:21.986 1811-1827/com.rainliu.androidexercise E/AndroidRuntime: FATAL EXCEPTION: Thread-107
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4607)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:835)
at android.view.View.requestLayout(View.java:15129)
at android.view.View.requestLayout(View.java:15129)
at android.view.View.requestLayout(View.java:15129)
at android.view.View.requestLayout(View.java:15129)
at android.view.View.requestLayout(View.java:15129)
at android.view.View.requestLayout(View.java:15129)
at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:292)
at android.view.View.requestLayout(View.java:15129)
at android.widget.TextView.checkForRelayout(TextView.java:6303)
at android.widget.TextView.setText(TextView.java:3547)
at android.widget.TextView.setText(TextView.java:3405)
at android.widget.TextView.setText(TextView.java:3380)
at com.rainliu.androidexercise.rxjava.RxJavaActivity$4$1.run(RxJavaActivity.java:320)
自API级别1以来,类Thread没有改变。
只是尝试过,而Thread.currentThread().getName()
在使用main
时使用.run()
或Thread-2
给我线程.start()
;虽然两者似乎都不是后台线程。
可以用Looper.myLooper() == Looper.getMainLooper()
验证...
或者与Looper.getMainLooper().getThread() == Thread.currentThread()
。
new Thread() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(Looper.myLooper() == Looper.getMainLooper()) {
mTextView.setText(Thread.currentThread().getName());
} else {
Log.w(LOG_TAG, "not the main thread");
}
}
}.run();
只看到Processes and Threads,这解释了为什么这样做......
尽管它会阻止main
线程一秒钟。
那么为什么它在Android 4.0上崩溃了,那里的线程名称是什么?
我刚刚发现了一个video,它解释了差异。