ReactiveX / RxAndroid

RxJava bindings for Android
Apache License 2.0
19.89k stars 2.95k forks source link

Shouldn't AndroidSchedulers.mainThread() act as Schedulers.immediate() when already on the main thread? #335

Closed danielesegato closed 7 years ago

danielesegato commented 7 years ago

This is more a discussion / question then anything else.

Let's take this code as example:

@Override
public void onResume() {
    Log.i("TEST", "Before subscription");
    Observable.just("hi!")
        .subscribeOn(AndroidSchedulers.mainThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(val -> Log.i("TEST", "Received: + val));
    Log.i("TEST", "After subscription");
}

it prints:

Before subscription
After subscription
Received: hi!

If executed on the main thread, wouldn't it be useful to have a way of making it print:

Before subscription
Received: hi!
After subscription

?

I'm thinking about how Loaders works, when you init() they immediately return the value if it has already been loaded.

The recyclerView is different in this but the old ListView didn't correctly resumed the list if you didn't set your data in the onCreated method of the Activity (if I recall correctly). I remember it resetting to the top.

I wouldn't change the current behavior for backward compatibility, but I'd add a new schedulers working like that if possible.

What do you think? Would it be useful?

akarnokd commented 7 years ago

This comes up often with GUI-type schedulers. The problem is with the recursive scheduling aspects of many flows is that they can pin the GUI thread processing one particular sequence and not executing GUI update requests from other sources. By doing this one by one, there is a much higher chance of mixing various actions and keeping the GUI responsive.

Besides, doing to much workload on the GUI thread is usually considered a bad thing. What you are suggesting is how Schedulers.from() works now and someone wanted to change to this GUI style here.

Each library can decide what's the reasonable to do and since RxJava is not a framework, you are free to implement your own scheduler (even by copying and modifying an existing one to your needs). Schedulers are one of the things that can live anywhere (unlike instance methods on Observable).

JakeWharton commented 7 years ago

Prior art: https://github.com/ReactiveX/RxAndroid/pull/228, https://github.com/JakeWharton/RxBinding/issues/28.

If you want something to run synchronously the answer is not schedule and ensure you're already on the main thread. If you are doing something like observeOn(mainThread()) but you don't know what thread the stream is on then that's the thing you need to fix.

Also more info here: https://www.youtube.com/watch?v=va1d4MqLUGY

PaulWoitaschek commented 7 years ago

Im still heavily struggling with this aspect of RxJava.

I have a manager class that returns data. It returns it from cache if available, else from network. My clients now need to apply observeOn so the network requests don't run on the UI thread. However this leads to the UI flashing when my ProgressBar displays for the fraction of a second when the data comes from cache. How can I handle that?

hyysgit commented 5 years ago

可以这样写:.subscribeOn(Schedulers.io()) .observeOn(Schedulers.from(new Executor(){ @Override public void execute(@android.support.annotation.NonNull Runnable command) { runOnUiThread(command); } }))

hyysgit commented 5 years ago

或者创建一个类 `package com.yongge.retrofit_test.utils;

import android.os.Handler; import android.os.Looper; import android.support.annotation.NonNull;

import java.util.concurrent.Executor;

import rx.Scheduler; import rx.schedulers.Schedulers;

/**

}

`