Какие изменения в Android 8 позволяют обновлять пользовательский интерфейс из не-пользовательского потока - PullRequest
0 голосов
/ 08 сентября 2018

В приведенном ниже примере кода он пытается обновить пользовательский интерфейс из не-пользовательского потока, он вылетает на 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)

1 Ответ

0 голосов
/ 08 сентября 2018

класс Тема не изменилась с уровня API 1.

только что попробовал, в то время как 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();

просто посмотрите Процессы и потоки , что объясняет, почему это работает ...

несмотря на то, что он заблокирует поток main на секунду.

так почему он вылетает на Android 4.0 и какие там имена потоков?

и я только что нашел видео , которое объясняет разницу.

...