22

I created simple activity with infinity progres bar, and I'am trying to run time consuming method using RxJava to prevent UI thread from blocking, but everytime UI thread is blocked. I think my solution has problem with emitting Observable. Can anyone help me? I'am begginer in RX.

public class MainActivity extends AppCompatActivity {

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

public void doSomething(View view) {
    doHeavyStuff()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnNext(new Action1() {
                @Override
                public void call(Object o) {
                    Toast.makeText(getApplicationContext(), "FINISHED", Toast.LENGTH_SHORT).show();
                }
            })
            .subscribe();
}

private Observable doHeavyStuff() {
    for (int i = 0; i < 999999999; i++) {
        for (int j = 0; j < 2; j++) {
        }
    }
    return Observable.just(1);

}
panbacuh
  • 622
  • 1
  • 9
  • 17

5 Answers5

34

With RxJava2 a possible solution is:

Version with lambdas:

Single.fromCallable(() -> loadInBackground())
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe((resultObject) -> { updateUi(resultObject) });

Version without lambdas:

Single.fromCallable(new Callable<Object>() {
    @Override
    public Object call() throws Exception {
        return loadInBackground();
    }
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Object>() {
    @Override
    public void accept(Object resultObject) throws Exception {
        updateUi(resultObject);
    }
 });

Example methods used above:

private Object loadInBackground() {
    // some heavy load code
    return resultObject;
}

private void updateUi(Object resultObject) {
    // update your Views here
}
vovahost
  • 34,185
  • 17
  • 113
  • 116
  • hi @vovahost The result of subscribe is not used ? – The Black Horse May 29 '18 at 09:42
  • I don't know what you mean. If you're are referring to the example, I didn't add more code to make it simple but you would use `myObject`. For example `myObject` can be a user object and you would display it's fields in a Profile screen. – vovahost May 29 '18 at 11:28
  • lint checks for your code shows message --->"The result of subscribe is not used" . I think IDE treats it as potentially unsafe – The Black Horse May 30 '18 at 11:41
  • You should post your code to pastebin and post here the link. Without actual code it's hard to say. – vovahost May 31 '18 at 08:27
  • can I use void return type for `loadInBackground()` method.. if yes then how i can use it? – Fra Red Mar 06 '19 at 10:11
  • @Fra Red Change it to: `Completable.fromRunnable(() -> loadInBackground()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(() -> { updateUi() });` – vovahost Mar 06 '19 at 10:47
11

According to docs

Deprecated: fromFunc0 Unnecessary now that Func0 extends Callable. Just call fromCallable(java.util.concurrent.Callable) instead.

So you could make the call in this way:

Observable.fromCallable(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                return someMethod();
            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Object>() {
                    @Override
                    public void call(Object object) {

                    }
                });
Mikelis Kaneps
  • 4,576
  • 2
  • 34
  • 48
10

Your doHeavyStuff() executes computation on calling thread, you just wrap your result into Observable. In order to wrap computation into observable you should use defer

Observable.defer(new Func0<Observable<Integer>>() {
    @Override
    public Observable<Integer> call() {
        return Observable.just(doHeavyStuff());
    }
});

then you can specify threads by subscribeOn and observeOn methods

krp
  • 2,247
  • 17
  • 14
10

kotlin use below code to work in background

 Single.fromCallable {
                  // method that run in background

          }
           .subscribeOn(Schedulers.io())
           .observeOn(AndroidSchedulers.mainThread())
           .subscribe()
Jai Khambhayta
  • 4,198
  • 2
  • 22
  • 29
1

Also, you can use RxJavaAsyncUtil:

compile 'io.reactivex:rxjava-async-util:0.21.0'

Code:

Observable.fromFunc0(() -> doHeavyStuff())