Android-RxJava:使用可观察对象从后台线程更新UI

huangapple go评论112阅读模式
英文:

Android-RxJava: Update UI from background thread using observable

问题

package com.example.reactiveTest;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;

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) {
        createObservable()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<String>() {
                @Override
                public void onSubscribe(Disposable d) {
                    // Disposable handling
                }

                @Override
                public void onNext(String string) {
                    result.setText(string);
                }

                @Override
                public void onError(Throwable e) {
                    // Handle error
                }

                @Override
                public void onComplete() {
                    // Handle completion
                }
            });
    }

    private Observable<String> createObservable() {
        return Observable.just("Just some String")
            .map(s -> {
                // Simulate server request and return response String
                return response;
            });
    }
}

Please note that this code assumes you have added the necessary RxJava and RxAndroid dependencies to your project. The above code demonstrates how to create and subscribe to an Observable using RxJava for performing the network request and updating the UI on the main thread.

英文:

I just started building a simple Android app, in which I'd like to make a network request in a background thread and then update the main thread (UI thread) with the servers response. So far I used AsyncTasks, but future implementations I'd like to use reactive Java (RxJava). I have never done reactive calls before, so I'd like to have a simple but complete example (Observable and Observer creation and subscription) upon which it is possible to further build on.

I managed to include the RxJava dependency into the basic Android project and have written a very simple main activity using AsyncTasks for the network request. Now I tried to substitute the AsyncTask implementation with a reactive one, but got stuck in all the information regarding the Observable and Observer. I'm just not sure what exactly is necessary for a minimum but fully working example.

I'd really apprechiate a bit of help in transforming the main parts into an reactive implementation, since I don't know how to handle the generation of the Observable from the response string and subscribe an Observer.

Thanks.

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(&quot;Just some String&quot;);
}
class SomeTask extends AsyncTask&lt;String, Void, String&gt; {
@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

得分: 4

使用AsyncTask,基本上你在工作线程上执行异步操作,然后在主线程上使用其结果。在Rx中,你会使用类似以下的方式:

Observable.fromCallable(asyncOperation)
.subscribeOn(backgroundThread)
.observeOn(mainThread)
.subscribe(result -> { /* 更新界面,例如 */ })

看起来你也对onNextonErroronComplete感兴趣。

  • 每当可观察对象发出项目时,都会调用onNext。每次调用时,它都会接收一个项目,然后可以处理它。
  • 当可观察对象由于任何原因遇到错误时,会调用onError。调用时,它会接收一个Throwable,表示错误的原因。在调用后,不会再调用onNext和onComplete。
  • 在调用最后一个项目的onNext后调用onComplete。它不接收任何输入,例如,你可以在其中进行一些清理工作。

使用上述方法如下:

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

【编辑】

如果你想使用Observable.create()来创建自己的Observable,当然可以,它可以更精细地控制通过Observable发出的内容以及发出的时间。例如,如果你想处理一些特定的网络请求错误,并根据错误类型发出不同的Throwable,就可以使用这种方式。

ObservableOnSubscribe asyncOperation = new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> emitter) {
try {
// 网络请求
// 一旦结果准备好,调用 emitter.onNext()。
// 完成后,通过调用 emitter.onComplete() 完成此Observable
} catch (Exception e) {
// 处理错误,并使用 emitter.onError() 发出错误
}
}
}
英文:

With AsyncTask, you're basically performing an asynchronous operation on a worker thread, then using its result on the main thread. In Rx you'd use something like the following:

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

It seems you're also interested in onNext, onError and onComplete.

  • onNext is called every time the observable emits an item. Each time it's called it receives an item, and can then process it.
  • onError is called when the observable has encountered an error for whatever reason. When it's called, it receives a Throwable, which represents the cause of the error. after it's called, onNext and onComplete are not called.
  • onComplete is called after onNext is called with the last item. It doesn't receive any input, you could do some clean up in it for example.

Using the above methods looks like this:

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

[Edit]

If you'd like to create your Observable using Observable.create(), you can definitely do that, it gives you finer control over what and when you emit through the Observable. You can do this for instance if you want to handle some specific errors that can result from your network request, and emit different Throwables depending on the error.

ObservableOnSubscribe asyncOperation = new Observable.OnSubscribe&lt;Integer&gt;() {
@Override
public void call(Subscriber&lt;? super Integer&gt; 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()
}
}
} 

huangapple
  • 本文由 发表于 2020年3月15日 08:46:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/60688724.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定