Added the watch logic to ThreadLoader

captchafix
Florens Douwes 12 years ago
parent 422e496dd7
commit 44e416b0ba
  1. 12
      Chan/src/org/floens/chan/fragment/ThreadFragment.java
  2. 82
      Chan/src/org/floens/chan/loader/Loader.java
  3. 3
      Chan/src/org/floens/chan/loader/LoaderPool.java
  4. 18
      Chan/src/org/floens/chan/manager/ThreadManager.java
  5. 26
      Chan/src/org/floens/chan/view/ThreadWatchCounterView.java
  6. 20
      Chan/src/org/floens/chan/watch/PinWatcher.java
  7. 140
      Chan/src/org/floens/chan/watch/WatchLogic.java

@ -96,20 +96,20 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana
} }
@Override @Override
public void onResume() { public void onStart() {
super.onResume(); super.onStart();
if (threadManager != null) { if (threadManager != null) {
threadManager.onResume(); threadManager.onStart();
} }
} }
@Override @Override
public void onPause() { public void onStop() {
super.onPause(); super.onStop();
if (threadManager != null) { if (threadManager != null) {
threadManager.onPause(); threadManager.onStop();
} }
} }

@ -8,6 +8,7 @@ import org.floens.chan.model.Loadable;
import org.floens.chan.model.Post; import org.floens.chan.model.Post;
import org.floens.chan.utils.Logger; import org.floens.chan.utils.Logger;
import android.os.Handler;
import android.util.SparseArray; import android.util.SparseArray;
import com.android.volley.Response; import com.android.volley.Response;
@ -16,13 +17,21 @@ import com.android.volley.VolleyError;
public class Loader { public class Loader {
private static final String TAG = "Loader"; private static final String TAG = "Loader";
private static final Handler handler = new Handler();
private static final int[] watchTimeouts = {10, 15, 20, 30, 60, 90, 120, 180, 240, 300};
private final List<LoaderListener> listeners = new ArrayList<LoaderListener>(); private final List<LoaderListener> listeners = new ArrayList<LoaderListener>();
private final Loadable loadable; private final Loadable loadable;
private ChanReaderRequest request; private final SparseArray<Post> postsById = new SparseArray<Post>();
private boolean destroyed = false; private boolean destroyed = false;
private ChanReaderRequest request;
private final SparseArray<Post> postsById = new SparseArray<Post>(); private int currentTimeout;
private int lastPostCount;
private long lastLoadTime;
private Runnable pendingRunnable;
public Loader(Loadable loadable) { public Loader(Loadable loadable) {
this.loadable = loadable; this.loadable = loadable;
@ -44,6 +53,7 @@ public class Loader {
public boolean removeListener(LoaderListener l) { public boolean removeListener(LoaderListener l) {
listeners.remove(l); listeners.remove(l);
if (listeners.size() == 0) { if (listeners.size() == 0) {
clearTimer();
destroyed = true; destroyed = true;
return true; return true;
} else { } else {
@ -81,10 +91,17 @@ public class Loader {
return; return;
} }
clearTimer();
request = getData(loadable); request = getData(loadable);
} }
} }
public void requestNextDataResetTimer() {
currentTimeout = 0;
requestNextData();
}
/** /**
* @return Returns if this loader is currently loading * @return Returns if this loader is currently loading
*/ */
@ -100,6 +117,60 @@ public class Loader {
return loadable; return loadable;
} }
public void onStart() {
if (loadable.isThreadMode()) {
requestNextDataResetTimer();
}
}
public void onStop() {
clearTimer();
}
public long getTimeUntilReload() {
long waitTime = watchTimeouts[currentTimeout] * 1000L;
return lastLoadTime + waitTime - System.currentTimeMillis();
}
private void setTimer(int postCount) {
if (pendingRunnable != null) {
clearTimer();
}
if (pendingRunnable == null) {
pendingRunnable = new Runnable() {
@Override
public void run() {
pendingRunnableCallback();
};
};
if (postCount > lastPostCount) {
currentTimeout = 0;
} else {
currentTimeout = Math.min(watchTimeouts.length - 1, currentTimeout + 1);
}
lastPostCount = postCount;
handler.postDelayed(pendingRunnable, watchTimeouts[currentTimeout] * 1000L);
}
}
private void clearTimer() {
if (pendingRunnable != null) {
handler.removeCallbacks(pendingRunnable);
pendingRunnable = null;
lastLoadTime = 0;
}
}
private void pendingRunnableCallback() {
Logger.d(TAG, "pending callback");
pendingRunnable = null;
requestNextData();
}
private ChanReaderRequest getData(Loadable loadable) { private ChanReaderRequest getData(Loadable loadable) {
Logger.i(TAG, "Requested " + loadable.board + ", " + loadable.no); Logger.i(TAG, "Requested " + loadable.board + ", " + loadable.no);
@ -132,6 +203,11 @@ public class Loader {
for (LoaderListener l : listeners) { for (LoaderListener l : listeners) {
l.onData(result, loadable.isBoardMode()); l.onData(result, loadable.isBoardMode());
} }
lastLoadTime = System.currentTimeMillis();
if (loadable.isThreadMode()) {
setTimer(result.size());
}
} }
private void onError(VolleyError error) { private void onError(VolleyError error) {
@ -147,6 +223,8 @@ public class Loader {
for (LoaderListener l : listeners) { for (LoaderListener l : listeners) {
l.onError(error); l.onError(error);
} }
clearTimer();
} }
public static interface LoaderListener { public static interface LoaderListener {

@ -4,7 +4,6 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.floens.chan.model.Loadable; import org.floens.chan.model.Loadable;
import org.floens.chan.utils.Logger;
public class LoaderPool { public class LoaderPool {
private static final String TAG = "LoaderPool"; private static final String TAG = "LoaderPool";
@ -22,8 +21,6 @@ public class LoaderPool {
} }
public Loader obtain(Loadable loadable, Loader.LoaderListener listener) { public Loader obtain(Loadable loadable, Loader.LoaderListener listener) {
Logger.d(TAG, "loaders size: " + loaders.size());
Loader loader = loaders.get(loadable); Loader loader = loaders.get(loadable);
if (loader == null) { if (loader == null) {
loader = new Loader(loadable); loader = new Loader(loadable);

@ -46,7 +46,7 @@ import com.android.volley.VolleyError;
* All PostView's need to have this referenced. * All PostView's need to have this referenced.
* This manages some things like pages, starting and stopping of loading, * This manages some things like pages, starting and stopping of loading,
* handling linkables, replies popups etc. * handling linkables, replies popups etc.
* onDestroy, onPause and onResume must be called from the activity/fragment * onDestroy, onStart and onStop must be called from the activity/fragment
*/ */
public class ThreadManager implements Loader.LoaderListener { public class ThreadManager implements Loader.LoaderListener {
private static final String TAG = "ThreadManager"; private static final String TAG = "ThreadManager";
@ -67,12 +67,16 @@ public class ThreadManager implements Loader.LoaderListener {
unbindLoader(); unbindLoader();
} }
public void onPause() { public void onStart() {
if (loader != null) {
loader.onStart();
}
} }
public void onResume() { public void onStop() {
if (loader != null) {
loader.onStop();
}
} }
public void bindLoader(Loadable loadable) { public void bindLoader(Loadable loadable) {
@ -135,6 +139,10 @@ public class ThreadManager implements Loader.LoaderListener {
return loader.getLoadable(); return loader.getLoadable();
} }
public Loader getLoader() {
return loader;
}
public void onThumbnailClicked(Post post) { public void onThumbnailClicked(Post post) {
threadManagerListener.onThumbnailClicked(post); threadManagerListener.onThumbnailClicked(post);
} }

@ -1,7 +1,7 @@
package org.floens.chan.view; package org.floens.chan.view;
import org.floens.chan.loader.Loader;
import org.floens.chan.manager.ThreadManager; import org.floens.chan.manager.ThreadManager;
import org.floens.chan.watch.WatchLogic;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
@ -57,22 +57,24 @@ public class ThreadWatchCounterView extends TextView implements View.OnClickList
@Override @Override
public void onClick(View v) { public void onClick(View v) {
tm.requestNextData(); Loader loader = tm.getLoader();
if (loader != null) {
loader.requestNextDataResetTimer();
}
ad.notifyDataSetChanged(); ad.notifyDataSetChanged();
} }
private void updateCounterText(ThreadManager threadManager) { private void updateCounterText(ThreadManager threadManager) {
// WatchLogic logic = threadManager.getWatchLogic(); Loader loader = tm.getLoader();
WatchLogic logic = null; if (loader == null) return;
if (logic != null) { int time = Math.round(loader.getTimeUntilReload() / 1000f);
int time = Math.round(logic.timeLeft() / 1000f);
if (time <= 0) {
if (time <= 0) { setText("Loading");
setText("Loading"); } else {
} else { setText("Loading in " + time);
setText("Loading in " + time);
}
} }
} }
} }

@ -3,7 +3,6 @@ package org.floens.chan.watch;
import java.util.List; import java.util.List;
import org.floens.chan.loader.Loader; import org.floens.chan.loader.Loader;
import org.floens.chan.model.Loadable;
import org.floens.chan.model.Pin; import org.floens.chan.model.Pin;
import org.floens.chan.model.Post; import org.floens.chan.model.Post;
import org.floens.chan.service.PinnedService; import org.floens.chan.service.PinnedService;
@ -15,31 +14,18 @@ public class PinWatcher implements Loader.LoaderListener {
private static final String TAG = "PinWatcher"; private static final String TAG = "PinWatcher";
private final Pin pin; private final Pin pin;
private final Loadable loadable;
private Loader loader; private Loader loader;
private final WatchLogic watchLogic;
private long startTime; private long startTime;
public PinWatcher(Pin pin) { public PinWatcher(Pin pin) {
this.pin = pin; this.pin = pin;
loadable = pin.loadable.copy();
loadable.simpleMode = true;
// loader = new Loader(this); // loader = new Loader(this);
watchLogic = new WatchLogic();
} }
public void update() { public void destroy() {
if (watchLogic.timeLeft() < 0L) {
Logger.test("PinWatcher update");
startTime = System.currentTimeMillis();
loader.requestData();
}
} }
@Override @Override
@ -60,8 +46,6 @@ public class PinWatcher implements Loader.LoaderListener {
pin.watchNewCount = count; pin.watchNewCount = count;
watchLogic.onLoaded(count, false);
Logger.test("Load time: " + (System.currentTimeMillis() - startTime) + "ms"); Logger.test("Load time: " + (System.currentTimeMillis() - startTime) + "ms");
PinnedService.callOnPinsChanged(); PinnedService.callOnPinsChanged();

@ -1,140 +0,0 @@
package org.floens.chan.watch;
import java.util.Timer;
import java.util.TimerTask;
import org.floens.chan.utils.Logger;
import org.floens.chan.utils.Utils;
public class WatchLogic {
private static final String TAG = "WatchLogic";
private static final int[] timeouts = {10, 15, 20, 30, 60, 90, 120, 180, 240, 300};
private WatchListener listener;
private int selectedTimeout;
private long lastLoadTime;
private int lastPostCount;
private Timer timer = new Timer();
public WatchLogic() {
}
public WatchLogic(WatchListener listener) {
this.listener = listener;
}
/**
* Stops the timer and removes the listener
*/
public void destroy() {
Logger.d(TAG, "Destroy");
this.listener = null;
clearTimer();
}
/**
* Starts the timer from the beginning
*/
public void startTimer() {
Logger.d(TAG, "Start timer");
lastLoadTime = now();
selectedTimeout = 0;
scheduleTimer();
}
/**
* Stops the timer
*/
public void stopTimer() {
Logger.d(TAG, "Stop timer");
clearTimer();
}
/**
* Call onWatchReloadRequested on the listener and reset the timer
*/
public void loadNow() {
clearTimer();
lastLoadTime = 0;
selectedTimeout = -1; // so that the next timeout will be the first one
if (listener != null) {
listener.onWatchReloadRequested();
}
}
/**
* Call this to notify of new posts.
* @param postCount how many posts there were loaded
*/
public void onLoaded(int postCount, boolean scheduleTimer) {
Logger.d(TAG, "Loaded. Post count " + postCount + ", last " + lastPostCount);
if (postCount > lastPostCount) {
selectedTimeout = 0;
} else {
selectedTimeout = Math.min(timeouts.length - 1, selectedTimeout + 1);
}
lastLoadTime = now();
lastPostCount = postCount;
if (scheduleTimer) {
scheduleTimer();
}
}
/**
* Time in ms left before a reload is necessary.
* @return
*/
public long timeLeft() {
long waitTime = timeouts[Math.max(0, selectedTimeout)] * 1000L;
return lastLoadTime + waitTime - now();
}
private void scheduleTimer() {
Logger.d(TAG, "Scheduling timer");
clearTimer();
timer.schedule(new TimerTask() {
@Override
public void run() {
if (listener != null) {
Utils.runOnUiThread(new Runnable() {
@Override
public void run() {
listener.onWatchReloadRequested();
}
});
}
}
}, Math.max(0, timeLeft()));
}
/**
* Clear all the scheduled runnables
*/
private void clearTimer() {
Logger.d(TAG, "Clearing timer");
timer.cancel();
timer.purge();
timer = new Timer();
}
private long now() {
return System.currentTimeMillis();
}
public interface WatchListener {
public void onWatchReloadRequested();
}
}
Loading…
Cancel
Save