package de.robv.android.xposed.installer.util; import android.support.v4.widget.SwipeRefreshLayout; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import de.robv.android.xposed.installer.XposedApp; public abstract class Loader<T> implements SwipeRefreshLayout.OnRefreshListener { protected final String CLASS_NAME = getClass().getSimpleName(); private boolean mIsLoading = false; private boolean mReloadTriggeredOnce = false; private final List<Listener<T>> mListeners = new CopyOnWriteArrayList<>(); private SwipeRefreshLayout mSwipeRefreshLayout; public void triggerReload(final boolean force) { synchronized (this) { if (!mReloadTriggeredOnce) { onFirstLoad(); mReloadTriggeredOnce = true; } } if (!force && !shouldUpdate()) { return; } synchronized (this) { if (mIsLoading) { return; } mIsLoading = true; updateProgressIndicator(); } new Thread("Reload" + CLASS_NAME) { public void run() { boolean hasChanged = onReload(); if (hasChanged) { notifyListeners(); } synchronized (this) { mIsLoading = false; updateProgressIndicator(); } } }.start(); } protected synchronized void onFirstLoad() { // Empty by default. } protected boolean shouldUpdate() { return true; } protected abstract boolean onReload(); public void clear(boolean notify) { synchronized (this) { // TODO Stop reloading repository when it should be cleared if (mIsLoading) { return; } onClear(); } if (notify) { notifyListeners(); } } protected abstract void onClear(); public void triggerFirstLoadIfNecessary() { synchronized (this) { if (mReloadTriggeredOnce) { return; } } triggerReload(false); } public synchronized boolean isLoading() { return mIsLoading; } public interface Listener<T> { void onReloadDone(T loader); } public void addListener(Listener<T> listener) { if (!mListeners.contains(listener)) { mListeners.add(listener); } } public void removeListener(Listener<T> listener) { mListeners.remove(listener); } protected void notifyListeners() { for (Listener<T> listener : mListeners) { //noinspection unchecked listener.onReloadDone((T) this); } } public synchronized void setSwipeRefreshLayout(SwipeRefreshLayout swipeRefreshLayout) { this.mSwipeRefreshLayout = swipeRefreshLayout; if (swipeRefreshLayout == null) { return; } swipeRefreshLayout.setRefreshing(mIsLoading); swipeRefreshLayout.setOnRefreshListener(this); } @Override public void onRefresh() { triggerReload(true); } private synchronized void updateProgressIndicator() { if (mSwipeRefreshLayout == null) { return; } XposedApp.runOnUiThread(new Runnable() { @Override public void run() { synchronized (Loader.this) { if (mSwipeRefreshLayout != null) { mSwipeRefreshLayout.setRefreshing(mIsLoading); } } } }); } }