Android -Rx Java: обновление пользовательского интерфейса из фонового потока с использованием наблюдаемого - PullRequest
1 голос
/ 15 марта 2020

Я только начал создавать простое приложение Android, в котором я хотел бы сделать сетевой запрос в фоновом потоке, а затем обновить основной поток (поток пользовательского интерфейса) ответом сервера. До сих пор я использовал AsyncTasks, но в будущих реализациях я хотел бы использовать реактивный Java (RxJava). Раньше я никогда не делал реактивные вызовы, поэтому я хотел бы иметь простой, но полный пример (создание и подписка Observable и Observer), на которых можно продолжить работу.

Мне удалось включить зависимость Rx Java в проект basi c Android и я написал очень простое основное действие, используя AsyncTasks для сетевого запроса. Теперь я попытался заменить реализацию AsyncTask на реактивную, но застрял во всей информации, касающейся Observable и Observer. Я просто не уверен, что именно необходимо для минимального, но полностью работающего примера.

Я бы очень хотел помочь в превращении основных частей в реактивную реализацию, поскольку не знаю, как обрабатывать генерацию Observable из строки ответа и подписывать Observer.

Спасибо.

package com.example.reactiveTest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private Button btnSend = null;
    private TextView result = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.btnSend = findViewById(R.id.button_send);
        this.result = findViewById(R.id.result);
    }

    public void onClickBtnSend(View view) {
        new SomeTask().execute("Just some String");
    }

    class SomeTask extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... strings) {
            // server request returning response String
            return response;
        }

        @Override
        protected void onPostExecute(String string) {
            // update UI with response String
            result.setText(string);
        }
    }
}

1 Ответ

2 голосов
/ 15 марта 2020

С AsyncTask вы в основном выполняете асинхронную операцию в рабочем потоке, а затем используете ее результат в основном потоке. В Rx вы бы использовали что-то вроде следующего:

Observable.fromCallable(asyncOperation)
   .subscribeOn(backgroundThread)
   .observeOn(mainThread)
   .subscribe(result -> { /* update UI for instance */ })

Кажется, вы также заинтересованы в onNext, onError и onComplete.

  • onNext вызывается каждый раз, когда наблюдаемое излучает предмет. Каждый раз, когда он вызывается, он получает элемент и затем может его обработать.
  • onError вызывается, когда наблюдаемое обнаружило ошибку по какой-либо причине. Когда он вызывается, он получает Throwable, который представляет причину ошибки. после вызова onNext и onComplete не вызываются.
  • onComplete вызывается после вызова onNext с последним элементом. Он не получает никаких входных данных, например, вы можете выполнить некоторую очистку.

Использование вышеуказанных методов выглядит следующим образом:

Observable.fromCallable(asyncOperation)
   .subscribeOn(backgroundThread)
   .observeOn(mainThread)
   .subscribe(onNext, onError, onComplete)

[Редактировать]

Если вы хотите создать свой Observable, используя Observable.create(), вы определенно можете это сделать, он дает вам более точный контроль над тем, что и когда вы излучаете через Observable. Это можно сделать, например, если вы хотите обработать некоторые конкретные c ошибки, которые могут возникнуть в результате вашего сетевого запроса, и выдать различные Throwable s в зависимости от ошибки.

ObservableOnSubscribe asyncOperation = new Observable.OnSubscribe<Integer>() {
    @Override
    public void call(Subscriber<? super Integer> emitter) {
        try {
            // network request
            // Once result is ready, call emitter.onNext().
            // When done, complete this Observable by calling emitter.onComplete()
        } catch (Exception e) {
            // handle error, and emit it using emitter.onError()
        }
    }
 } 
...