mirror of https://github.com/NekoX-Dev/NekoX.git
132 lines
4.3 KiB
Java
132 lines
4.3 KiB
Java
package org.telegram.messenger;
|
|
|
|
import android.util.Pair;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
|
|
public abstract class Fetcher<Args, R> {
|
|
|
|
protected void getRemote(int currentAccount, Args arguments, long hash, Utilities.Callback3<Boolean, R, Long> onResult) {
|
|
// Implement this function
|
|
}
|
|
|
|
// Not specifying getLocal and setLocal would mean that data is cached only in RAM
|
|
protected void getLocal(int currentAccount, Args arguments, Utilities.Callback2<Long, R> onResult) {
|
|
// Implement this function
|
|
onResult.run(0L, null);
|
|
}
|
|
|
|
protected void setLocal(int currentAccount, Args arguments, R data, long hash) {
|
|
// Implement this function
|
|
}
|
|
|
|
private long requestRemotelyTimeout = 4 * 60 * 1000;
|
|
|
|
private HashMap<Pair<Integer, Args>, R> cachedResults;
|
|
private HashMap<Pair<Integer, Args>, ArrayList<Utilities.Callback<R>>> loadingCallbacks;
|
|
private HashMap<Pair<Integer, Args>, Long> lastRequestedRemotely;
|
|
|
|
public void fetch(int currentAccount, Args arguments, Utilities.Callback<R> onResult) {
|
|
final Pair<Integer, Args> key = new Pair<>(currentAccount, arguments);
|
|
|
|
if (isLoading(key)) {
|
|
saveCallback(key, onResult);
|
|
return;
|
|
}
|
|
|
|
R cached = getCachedResult(key);
|
|
if (cached != null && !shouldRequest(key)) {
|
|
if (onResult != null) {
|
|
onResult.run(cached);
|
|
}
|
|
return;
|
|
}
|
|
|
|
saveCallback(key, onResult);
|
|
getLocal(currentAccount, arguments, (hash, data) -> {
|
|
if (shouldRequest(key)) {
|
|
saveLastRequested(key);
|
|
getRemote(currentAccount, arguments, hash, (notModified, remoteData, newHash) -> {
|
|
if (notModified) {
|
|
cacheResult(key, data);
|
|
callCallbacks(key, data);
|
|
} else {
|
|
if (remoteData != null) {
|
|
setLocal(currentAccount, arguments, remoteData, newHash);
|
|
cacheResult(key, remoteData);
|
|
}
|
|
callCallbacks(key, remoteData);
|
|
}
|
|
});
|
|
} else {
|
|
cacheResult(key, data);
|
|
callCallbacks(key, data);
|
|
}
|
|
});
|
|
}
|
|
|
|
private R getCachedResult(Pair<Integer, Args> key) {
|
|
if (cachedResults == null) {
|
|
return null;
|
|
}
|
|
return cachedResults.get(key);
|
|
}
|
|
|
|
private void cacheResult(Pair<Integer, Args> key, R result) {
|
|
if (cachedResults == null) {
|
|
cachedResults = new HashMap<>();
|
|
}
|
|
cachedResults.put(key, result);
|
|
}
|
|
|
|
private void saveLastRequested(Pair<Integer, Args> key) {
|
|
if (lastRequestedRemotely == null) {
|
|
lastRequestedRemotely = new HashMap<>();
|
|
}
|
|
lastRequestedRemotely.put(key, System.currentTimeMillis());
|
|
}
|
|
|
|
private boolean shouldRequest(Pair<Integer, Args> key) {
|
|
Long lastRequested = lastRequestedRemotely != null ? lastRequestedRemotely.get(key) : null;
|
|
return lastRequested == null || System.currentTimeMillis() - lastRequested >= requestRemotelyTimeout;
|
|
}
|
|
|
|
private boolean isLoading(Pair<Integer, Args> key) {
|
|
return loadingCallbacks != null && loadingCallbacks.get(key) != null;
|
|
}
|
|
|
|
private void saveCallback(Pair<Integer, Args> key, Utilities.Callback<R> callback) {
|
|
if (callback == null) {
|
|
return;
|
|
}
|
|
if (loadingCallbacks == null) {
|
|
loadingCallbacks = new HashMap<>();
|
|
}
|
|
ArrayList<Utilities.Callback<R>> callbacks = loadingCallbacks.get(key);
|
|
if (callbacks == null) {
|
|
loadingCallbacks.put(key, callbacks = new ArrayList<>());
|
|
}
|
|
callbacks.add(callback);
|
|
}
|
|
|
|
private void callCallbacks(Pair<Integer, Args> key, R result) {
|
|
if (loadingCallbacks == null) {
|
|
return;
|
|
}
|
|
|
|
final ArrayList<Utilities.Callback<R>> callbacks = loadingCallbacks.get(key);
|
|
if (callbacks == null) {
|
|
return;
|
|
}
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
for (Utilities.Callback<R> callback: callbacks) {
|
|
callback.run(result);
|
|
}
|
|
callbacks.clear();
|
|
});
|
|
|
|
loadingCallbacks.remove(key);
|
|
}
|
|
} |