Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package be.digitalia.arch.lifecycle;
- import android.arch.lifecycle.LiveData;
- import android.arch.lifecycle.MutableLiveData;
- import android.os.AsyncTask;
- import android.support.annotation.MainThread;
- import android.support.annotation.NonNull;
- import android.support.annotation.VisibleForTesting;
- import android.support.annotation.WorkerThread;
- import java.util.concurrent.atomic.AtomicBoolean;
- /**
- * A LiveData class that can be invalidated & computed on demand.
- *
- * @param <T> The type of the live data
- */
- public abstract class ComputableLiveData<T> {
- private final MutableLiveData<T> mLiveData;
- private final AtomicBoolean mInvalid = new AtomicBoolean(true);
- private final AtomicBoolean mComputing = new AtomicBoolean(false);
- /**
- * Creates a computable live data which is computed when there are active observers.
- * <p>
- * It can also be invalidated via {@link #invalidate()} which will result in a call to
- * {@link #compute()} if there are active observers (or when they start observing)
- */
- public ComputableLiveData() {
- mLiveData = new MutableLiveData<T>() {
- @Override
- protected void onActive() {
- AsyncTask.THREAD_POOL_EXECUTOR.execute(mRefreshRunnable);
- }
- };
- }
- /**
- * Returns the LiveData managed by this class.
- *
- * @return A LiveData that is controlled by ComputableLiveData.
- */
- @NonNull
- public LiveData<T> getLiveData() {
- return mLiveData;
- }
- @VisibleForTesting
- final Runnable mRefreshRunnable = new Runnable() {
- @WorkerThread
- @Override
- public void run() {
- boolean computed;
- do {
- computed = false;
- if (mComputing.compareAndSet(false, true)) {
- try {
- T value = null;
- while (mInvalid.compareAndSet(true, false)) {
- computed = true;
- value = compute();
- }
- if (computed) {
- mLiveData.postValue(value);
- }
- } finally {
- mComputing.set(false);
- }
- }
- } while (computed && mInvalid.get());
- }
- };
- /**
- * Invalidates the LiveData.
- * <p>
- * When there are active observers, this will trigger a call to {@link #compute()}.
- */
- @MainThread
- public void invalidate() {
- boolean isActive = mLiveData.hasActiveObservers();
- if (mInvalid.compareAndSet(false, true)) {
- if (isActive) {
- AsyncTask.THREAD_POOL_EXECUTOR.execute(mRefreshRunnable);
- }
- }
- }
- @SuppressWarnings("WeakerAccess")
- @WorkerThread
- protected abstract T compute();
- }
Add Comment
Please, Sign In to add comment