NekoX/TMessagesProj/src/main/java/org/telegram/messenger/Fetcher.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);
}
}