mirror of https://github.com/kurisufriend/Clover
parent
f3db76eef6
commit
fbefe1ed33
@ -1,106 +0,0 @@ |
|||||||
package org.floens.chan.activity; |
|
||||||
|
|
||||||
import org.floens.chan.R; |
|
||||||
import org.floens.chan.fragment.ThreadFragment; |
|
||||||
import org.floens.chan.model.Loadable; |
|
||||||
import org.floens.chan.model.Pin; |
|
||||||
import org.floens.chan.model.Post; |
|
||||||
import org.floens.chan.model.Loadable.Mode; |
|
||||||
import org.floens.chan.net.ChanUrls; |
|
||||||
|
|
||||||
import android.os.Bundle; |
|
||||||
import android.text.TextUtils; |
|
||||||
import android.view.Menu; |
|
||||||
import android.view.MenuItem; |
|
||||||
|
|
||||||
public class CatalogActivity extends BaseActivity { |
|
||||||
private final Loadable loadable = new Loadable(); |
|
||||||
|
|
||||||
private ThreadFragment threadFragment; |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onOPClicked(Post post) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void openPin(Pin post) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void onCreate(Bundle savedInstanceState) { |
|
||||||
super.onCreate(savedInstanceState); |
|
||||||
|
|
||||||
loadable.mode = Mode.CATALOG; |
|
||||||
|
|
||||||
threadFragment = ThreadFragment.newInstance(this); |
|
||||||
/*FragmentTransaction ft = getFragmentManager().beginTransaction(); |
|
||||||
ft.replace(R.id.container, threadFragment); |
|
||||||
ft.commitAllowingStateLoss();*/ |
|
||||||
|
|
||||||
Bundle bundle = getIntent().getExtras(); |
|
||||||
|
|
||||||
// Favor savedInstanceState bundle over intent bundle:
|
|
||||||
// the intent bundle may be old, for example when the user
|
|
||||||
// switches the loadable through the drawer.
|
|
||||||
if (savedInstanceState != null) { |
|
||||||
loadable.readFromBundle(this, savedInstanceState); |
|
||||||
} else if (bundle != null) { |
|
||||||
loadable.readFromBundle(this, bundle); |
|
||||||
} else { |
|
||||||
finish(); |
|
||||||
} |
|
||||||
|
|
||||||
startLoading(loadable); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected void onSaveInstanceState(Bundle outState) { |
|
||||||
super.onSaveInstanceState(outState); |
|
||||||
|
|
||||||
loadable.writeToBundle(this, outState); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean onOptionsItemSelected(MenuItem item) { |
|
||||||
switch(item.getItemId()) { |
|
||||||
case R.id.action_reload: |
|
||||||
threadFragment.reload(); |
|
||||||
|
|
||||||
return true; |
|
||||||
case R.id.action_open_browser: |
|
||||||
showUrlOpenPicker(ChanUrls.getCatalogUrlDesktop(loadable.board)); |
|
||||||
|
|
||||||
return true; |
|
||||||
case android.R.id.home: |
|
||||||
finish(); |
|
||||||
|
|
||||||
return true; |
|
||||||
default: |
|
||||||
return super.onOptionsItemSelected(item); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean onCreateOptionsMenu(Menu menu) { |
|
||||||
return super.onCreateOptionsMenu(menu); |
|
||||||
} |
|
||||||
|
|
||||||
private void startLoading(Loadable loadable) { |
|
||||||
threadFragment.startLoading(loadable); |
|
||||||
|
|
||||||
setShareUrl(ChanUrls.getCatalogUrlDesktop(loadable.board)); |
|
||||||
|
|
||||||
if (TextUtils.isEmpty(loadable.title)) { |
|
||||||
loadable.title = "Catalog /" + loadable.board + "/"; |
|
||||||
} |
|
||||||
|
|
||||||
getActionBar().setTitle(loadable.title); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,155 @@ |
|||||||
|
package org.floens.chan.loader; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.floens.chan.ChanApplication; |
||||||
|
import org.floens.chan.model.Loadable; |
||||||
|
import org.floens.chan.model.Post; |
||||||
|
import org.floens.chan.utils.Logger; |
||||||
|
|
||||||
|
import android.util.SparseArray; |
||||||
|
|
||||||
|
import com.android.volley.Response; |
||||||
|
import com.android.volley.ServerError; |
||||||
|
import com.android.volley.VolleyError; |
||||||
|
|
||||||
|
public class Loader { |
||||||
|
private static final String TAG = "Loader"; |
||||||
|
|
||||||
|
private final List<LoaderListener> listeners = new ArrayList<LoaderListener>(); |
||||||
|
private final Loadable loadable; |
||||||
|
private ChanReaderRequest request; |
||||||
|
private boolean destroyed = false; |
||||||
|
|
||||||
|
private final SparseArray<Post> postsById = new SparseArray<Post>(); |
||||||
|
|
||||||
|
public Loader(Loadable loadable) { |
||||||
|
this.loadable = loadable; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add a LoaderListener |
||||||
|
* @param l the listener to add |
||||||
|
*/ |
||||||
|
public void addListener(LoaderListener l) { |
||||||
|
listeners.add(l); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Remove a LoaderListener |
||||||
|
* @param l the listener to remove |
||||||
|
* @return true if there are no more listeners, false otherwise |
||||||
|
*/ |
||||||
|
public boolean removeListener(LoaderListener l) { |
||||||
|
listeners.remove(l); |
||||||
|
if (listeners.size() == 0) { |
||||||
|
destroyed = true; |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void requestData() { |
||||||
|
if (request != null) { |
||||||
|
request.cancel(); |
||||||
|
} |
||||||
|
|
||||||
|
postsById.clear(); |
||||||
|
|
||||||
|
if (loadable.isBoardMode()) { |
||||||
|
loadable.no = 0; |
||||||
|
loadable.listViewIndex = 0; |
||||||
|
loadable.listViewTop = 0; |
||||||
|
} |
||||||
|
|
||||||
|
request = getData(loadable); |
||||||
|
} |
||||||
|
|
||||||
|
public void requestNextData() { |
||||||
|
if (loadable.isBoardMode()) { |
||||||
|
loadable.no++; |
||||||
|
|
||||||
|
if (request != null) { |
||||||
|
request.cancel(); |
||||||
|
} |
||||||
|
|
||||||
|
request = getData(loadable); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return Returns if this loader is currently loading |
||||||
|
*/ |
||||||
|
public boolean isLoading() { |
||||||
|
return request != null; |
||||||
|
} |
||||||
|
|
||||||
|
public Post getPostById(int id) { |
||||||
|
return postsById.get(id); |
||||||
|
} |
||||||
|
|
||||||
|
public Loadable getLoadable() { |
||||||
|
return loadable; |
||||||
|
} |
||||||
|
|
||||||
|
private ChanReaderRequest getData(Loadable loadable) { |
||||||
|
Logger.i(TAG, "Requested " + loadable.board + ", " + loadable.no); |
||||||
|
|
||||||
|
ChanReaderRequest request = ChanReaderRequest.newInstance(loadable, new Response.Listener<List<Post>>() { |
||||||
|
@Override |
||||||
|
public void onResponse(List<Post> list) { |
||||||
|
Loader.this.request = null; |
||||||
|
onData(list); |
||||||
|
} |
||||||
|
}, new Response.ErrorListener() { |
||||||
|
@Override |
||||||
|
public void onErrorResponse(VolleyError error) { |
||||||
|
Loader.this.request = null; |
||||||
|
onError(error); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
ChanApplication.getVolleyRequestQueue().add(request); |
||||||
|
|
||||||
|
return request; |
||||||
|
} |
||||||
|
|
||||||
|
private void onData(List<Post> result) { |
||||||
|
if (destroyed) return; |
||||||
|
|
||||||
|
for (Post post : result) { |
||||||
|
postsById.append(post.no, post); |
||||||
|
} |
||||||
|
|
||||||
|
for (LoaderListener l : listeners) { |
||||||
|
l.onData(result); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void onError(VolleyError error) { |
||||||
|
if (destroyed) return; |
||||||
|
|
||||||
|
Logger.e(TAG, "Error loading " + error.getMessage(), error); |
||||||
|
|
||||||
|
// 404 with more pages already loaded means endofline
|
||||||
|
if ((error instanceof ServerError) && loadable.isBoardMode() && loadable.no > 0) { |
||||||
|
error = new EndOfLineException(); |
||||||
|
} |
||||||
|
|
||||||
|
for (LoaderListener l : listeners) { |
||||||
|
l.onError(error); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static interface LoaderListener { |
||||||
|
public void onData(List<Post> result); |
||||||
|
public void onError(VolleyError error); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,47 @@ |
|||||||
|
package org.floens.chan.loader; |
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.floens.chan.model.Loadable; |
||||||
|
import org.floens.chan.utils.Logger; |
||||||
|
|
||||||
|
public class LoaderPool { |
||||||
|
private static final String TAG = "LoaderPool"; |
||||||
|
|
||||||
|
private static LoaderPool instance; |
||||||
|
|
||||||
|
private static Map<Loadable, Loader> loaders = new HashMap<Loadable, Loader>(); |
||||||
|
|
||||||
|
public static LoaderPool getInstance() { |
||||||
|
if (instance == null) { |
||||||
|
instance = new LoaderPool(); |
||||||
|
} |
||||||
|
|
||||||
|
return instance; |
||||||
|
} |
||||||
|
|
||||||
|
public Loader obtain(Loadable loadable, Loader.LoaderListener listener) { |
||||||
|
Logger.d(TAG, "loaders size: " + loaders.size()); |
||||||
|
|
||||||
|
Loader loader = loaders.get(loadable); |
||||||
|
if (loader == null) { |
||||||
|
loader = new Loader(loadable); |
||||||
|
loaders.put(loadable, loader); |
||||||
|
} |
||||||
|
|
||||||
|
loader.addListener(listener); |
||||||
|
|
||||||
|
return loader; |
||||||
|
} |
||||||
|
|
||||||
|
public void release(Loader loader, Loader.LoaderListener listener) { |
||||||
|
if (!loaders.containsValue(loader)) { |
||||||
|
throw new RuntimeException("The released loader does not exist"); |
||||||
|
} |
||||||
|
|
||||||
|
if (loader.removeListener(listener)) { |
||||||
|
loaders.remove(loader); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,124 +0,0 @@ |
|||||||
package org.floens.chan.loader; |
|
||||||
|
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import org.floens.chan.ChanApplication; |
|
||||||
import org.floens.chan.model.Loadable; |
|
||||||
import org.floens.chan.model.Post; |
|
||||||
import org.floens.chan.utils.Logger; |
|
||||||
|
|
||||||
import android.util.SparseArray; |
|
||||||
|
|
||||||
import com.android.volley.Response; |
|
||||||
import com.android.volley.ServerError; |
|
||||||
import com.android.volley.VolleyError; |
|
||||||
|
|
||||||
public class ThreadLoader { |
|
||||||
private static final String TAG = "ThreadLoader"; |
|
||||||
|
|
||||||
private final ThreadLoaderListener listener; |
|
||||||
private ChanReaderRequest loader; |
|
||||||
private boolean stopped = false; |
|
||||||
private boolean loading = false; |
|
||||||
private Loadable loadable; |
|
||||||
private final SparseArray<Post> postsById = new SparseArray<Post>(); |
|
||||||
|
|
||||||
public ThreadLoader(ThreadLoaderListener listener) { |
|
||||||
this.listener = listener; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @return Returns if this loader is currently loading |
|
||||||
*/ |
|
||||||
public boolean isLoading() { |
|
||||||
return loading; |
|
||||||
} |
|
||||||
|
|
||||||
// public void start(int mode, String board, int pageOrThreadId) {
|
|
||||||
public void start(Loadable loadable) { |
|
||||||
Logger.i(TAG, "Start loading " + loadable.board + ", " + loadable.no); |
|
||||||
|
|
||||||
stop(); |
|
||||||
stopped = false; |
|
||||||
|
|
||||||
this.loadable = loadable; |
|
||||||
loader = getData(loadable); |
|
||||||
} |
|
||||||
|
|
||||||
public void loadMore() { |
|
||||||
if (loadable.isBoardMode()) { |
|
||||||
loadable.no++; |
|
||||||
start(loadable); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public void stop() { |
|
||||||
if (loader != null) { |
|
||||||
// Logger.i(TAG, "Stop loading");
|
|
||||||
loader.cancel(); |
|
||||||
loader = null; |
|
||||||
} |
|
||||||
|
|
||||||
postsById.clear(); |
|
||||||
|
|
||||||
stopped = true; |
|
||||||
} |
|
||||||
|
|
||||||
public Post getPostById(int id) { |
|
||||||
return postsById.get(id); |
|
||||||
} |
|
||||||
|
|
||||||
private ChanReaderRequest getData(Loadable loadable) { |
|
||||||
ChanReaderRequest request = ChanReaderRequest.newInstance(loadable, new Response.Listener<List<Post>>() { |
|
||||||
@Override |
|
||||||
public void onResponse(List<Post> list) { |
|
||||||
loading = false; |
|
||||||
onData(list); |
|
||||||
} |
|
||||||
}, new Response.ErrorListener() { |
|
||||||
@Override |
|
||||||
public void onErrorResponse(VolleyError error) { |
|
||||||
loading = false; |
|
||||||
onError(error); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
ChanApplication.getVolleyRequestQueue().add(request); |
|
||||||
loading = true; |
|
||||||
|
|
||||||
return request; |
|
||||||
} |
|
||||||
|
|
||||||
private void onData(List<Post> result) { |
|
||||||
if (stopped) return; |
|
||||||
|
|
||||||
for (Post post : result) { |
|
||||||
postsById.append(post.no, post); |
|
||||||
} |
|
||||||
|
|
||||||
listener.onData(result); |
|
||||||
} |
|
||||||
|
|
||||||
private void onError(VolleyError error) { |
|
||||||
if (stopped) return; |
|
||||||
|
|
||||||
Logger.e(TAG, "Error loading" + error.getMessage(), error); |
|
||||||
|
|
||||||
// 404 with more pages already loaded means endofline
|
|
||||||
if ((error instanceof ServerError) && loadable.isBoardMode() && loadable.no > 0) { |
|
||||||
error = new EndOfLineException(); |
|
||||||
} |
|
||||||
|
|
||||||
listener.onError(error); |
|
||||||
} |
|
||||||
|
|
||||||
public static abstract interface ThreadLoaderListener { |
|
||||||
public abstract void onData(List<Post> result); |
|
||||||
public abstract void onError(VolleyError error); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in new issue