0

I have a singleton that takes a few seconds to instantiate. It makes the UI freezes. So I'm planning to make the getInstance() method asynchronous. Is writing the following code a common practice?

/*
 * The singleton class
 */
public class Singleton {

    private static volatile Singleton instance;

    public static Observable<Singleton> getInstance(Context context) {
        return Observable.fromCallable(() -> {
            synchronized (Singleton.class) {
                if (instance == null)
                    instance = new Singleton(context.getApplicationContext());
            }
            return instance;
        });
    }

    private Singleton(Context context) {
        // long running process
    }

    // ...
}



/*
 * The UI class
 */
public class UI extends Activity {

    private Singleton singleton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Singleton.getInstance(this)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(result -> {
                UI.this.singleton = result
            })
    }

    public void onButtonClick(View v) {
        if (singleton != null)
            singleton.someMethod();
    }
}

If it's not, why isn't it and what's the better solution?

  • 1
    No. It is not. [Use an `enum` to implement singleton](https://stackoverflow.com/a/26285591/2970947). – Elliott Frisch Dec 26 '19 at 05:25
  • No, on the contrary, it is completely and utterly pointless. When you need the singleton you need it. There is mo point whatsoever I n introducing an asynchronous mechanism and then just waiting for its result. – user207421 Dec 26 '19 at 05:57
  • 1
    @user207421 Without asynchronous, the user can't interact with the UI for a few seconds because the UI freezes and that would be bad for UX. With asynchronous, the user can interact with the UI while the singleton is being instantiated. Why is it pointless? – Andika Wasisto Dec 26 '19 at 07:28
  • @ElliottFrisch It doesn't solve the problem that the instance takes a while to instantiate. The UI still freezes when the thread is instantiating the singleton – Andika Wasisto Dec 26 '19 at 07:44
  • There is no real asynchronous behaviour here. You are starting an async task and immediately waiting for its completion. That will also freeze the GUI. – user207421 Dec 26 '19 at 08:17
  • @user207421 I never said I immediately wait for its completion. Check out the UI class on the edited code – Andika Wasisto Dec 26 '19 at 10:07
  • You didn't have to say anything about it. Your code *does* it. – user207421 Dec 26 '19 at 11:58
  • 1
    @user207421 Have you read the UI class on the edited code? I clearly call the `getInstance` method asynchronously from the `onCreate` method and use the created instance later when the user touches a button – Andika Wasisto Dec 26 '19 at 12:45
  • @user207421 If I'm calling the `getInstance` method synchronously, I'd be using `blockingSingle` instead of `subscribe` – Andika Wasisto Dec 26 '19 at 13:00
  • what you want is to get the value asynchronously once and then use the cached the value ? – bubbles Dec 26 '19 at 14:07
  • @bubbles Yes, pretty much like that – Andika Wasisto Dec 26 '19 at 15:00

2 Answers2

0

What you want is to cache the value returned from the callable, so the next time you call subscribe you do not want to execute the Callable again. For that use cache operator.

Single<Integer> cachedValue = Single.fromCallable(() -> {
    Thread.sleep(3000);
    return 5;
}).cache();


cachedValue.subscribe(e -> System.out.println(System.currentTimeMillis() + ": " + e));
cachedValue.subscribe(e -> System.out.println(System.currentTimeMillis() + ": " + e));

You'll notice that the time for the second call is too close to the first one. At least < 3000 MS.

bubbles
  • 2,597
  • 1
  • 15
  • 40
-1

Check this Safe Singleton. Enums are the way to make it safe singleton

  • It doesn't solve the problem that the instance takes a while to instantiate. The UI still freezes when the thread is instantiating the singleton – Andika Wasisto Dec 26 '19 at 07:44