Как textView.setText из Thread?

Мне нужно установить текст в textView из потока. Весь код создается в oncreate()

что-то вроде

public TextView pc;

    oncreate(..) {
        setContentView(R.layout.main);
        pc = new TextView(context);
        Thread t =new Thread() {
            public void run() {
                pc.setText("test");
        }};
        t.start();

Это отменит мое приложение. Как установить текст из потока?

Ответы

Ответ 1

Используйте Handler:

public TextView pc;
Handler handler = new Handler();
oncreate(..) {
    setContentView(R.layout.main);
    pc = new TextView(context);
    Thread t =new Thread(){
        public void run() {
            handler.post(new Runnable() {
                public void run() {
                    pc.setText("test");
                }
            });
        }
    }};
    t.start();
}

Но у вас есть еще одна проблема. pc указывает на представление, которое не является частью вашей иерархии. Вероятно, вы захотите использовать findViewById с идентификатором TextView в своем макете.

Ответ 2

Попробуйте Activity.runOnUiThread().

Thread t = new Thread() {
    public void run() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                pc.setText("test");
            }
        });
    }
};

Ответ 3

Используя Android Data Binding Library, вы можете сделать это легко

Фоновая тема

Вы можете изменить свою модель данных в фоновом режиме нить, пока это не коллекция. Связывание данных будет локализовать каждая переменная/поле при оценке, чтобы избежать любого concurrencyвопросы.

Например

ViewModel.java

package somepackage;

public class ViewModel {
    public final ObservableField<String> mTextViewField = new ObservableField<>();

    public void setText(String text) {
        mTextViewField.set(text)
    }
}

main.xml

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type="somepackage.ViewModel" />

    </data>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewModel.mTextViewField}" />

    </FrameLayout>
</layout>

MainActivity.java

public class MainActivity {

    private ViewModel mViewModel;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        MainBinding binding = DataBindingUtil.setContentView(this, R.layout.main);

        mViewModel = new ViewModel();
        binding.setViewModel(viewModel);
    }

}

Теперь вы можете обращаться к mViewModel из любого потока и безопасно изменять текстовое значение