@@ -78,18 +78,25 @@ public void sort(Comparator<T> sorter) {
7878 private final Env <T > mEnv ;
7979 private final ExternalCacheManager mCache ;
8080 private final String mCacheKey ;
81+ private final int mMaxCacheStalenessMillis ;
8182 private final ProgressBar mProgressBar ;
83+ private final T [] mTmpArray ;
8284
83- public GenericListUpdater (Env <T > env ,
85+ public GenericListUpdater (
86+ Env <T > env ,
8487 Context context ,
8588 String cacheKey ,
86- ProgressBar progressBar ) {
89+ int maxCacheStalenessMillis ,
90+ ProgressBar progressBar ,
91+ T [] tmpArray ) {
8792 mContext = context ;
8893 mAdapter = new MyAdapter (context );
8994 mEnv = env ;
9095 mCache = ExternalCacheManager .getInstance (context .getApplicationContext ());
96+ mMaxCacheStalenessMillis = maxCacheStalenessMillis ;
9197 mCacheKey = cacheKey ;
9298 mProgressBar = progressBar ;
99+ mTmpArray = tmpArray ;
93100 if (mProgressBar != null ) mProgressBar .setVisibility (View .INVISIBLE );
94101 }
95102
@@ -127,14 +134,21 @@ public ListingStatus(T[] o, boolean d) {
127134 public final boolean deleteExistingObjects ;
128135 }
129136
130- private class ParallelFetcher {
131- private ExecutorService mThreads ;
132- private ArrayList <T []> mResults ;
133- private boolean [] mDone ;
137+ /**
138+ * Helper class for fetching multiple streams, as provided by myEnv, in parallel.
139+ *
140+ * The results are always yielded in the order listed in myEnv.
141+ */
142+ private static class ParallelFetcher <T > {
143+ private final Env <T > mEnv ;
144+ private final ExecutorService mThreads ;
145+ private final ArrayList <T []> mResults ;
146+ private final boolean [] mDone ;
134147 private int mNextIndexToRead ;
135148 private String mError ;
136149
137- public ParallelFetcher () {
150+ public ParallelFetcher (Env <T > env ) {
151+ mEnv = env ;
138152 final int numStreams = mEnv .numStreams ();
139153 mNextIndexToRead = 0 ;
140154 int numThreads = numStreams ;
@@ -154,6 +168,8 @@ public void shutdown() {
154168 mThreads .shutdown ();
155169 }
156170
171+ public synchronized boolean hasNext () { return mNextIndexToRead < mDone .length ; }
172+
157173 public synchronized T [] next () {
158174 while (!mDone [mNextIndexToRead ]) {
159175 try {
@@ -163,12 +179,10 @@ public synchronized T[] next() {
163179 }
164180 T [] r = mResults .get (mNextIndexToRead );
165181 ++mNextIndexToRead ;
166- Log .d (TAG , "RETURN: " + String .valueOf (mNextIndexToRead ) + ": " + String .valueOf (r != null ? r .length : -1 ));
167182 return r ;
168183 }
169184
170185 private synchronized void yieldResult (int index , T [] r ) {
171- Log .d (TAG , "Yield : " + String .valueOf (index ) + ": " + String .valueOf (r != null ? r .length : -1 ));
172186 mResults .set (index , r );
173187 mDone [index ] = true ;
174188 notify ();
@@ -179,11 +193,9 @@ private synchronized void setError(String e) {
179193 }
180194
181195 private class Fetcher implements Runnable {
182- final int mIndex ;
196+ private final int mIndex ;
183197
184- public Fetcher (int index ) {
185- mIndex = index ;
186- }
198+ public Fetcher (int index ) { mIndex = index ; }
187199
188200 public void run () {
189201 T [] objs = null ;
@@ -200,51 +212,47 @@ public void run() {
200212 }
201213 }
202214
203- /**
204- * @param mode either FORCE_RELOAD or MAY_READ_FROM_CACHE
205- *
206- * @return an error message, or null on success
207- */
208215 private class ListThread extends AsyncTask <Integer , ListingStatus <T >, String > {
216+ /**
217+ * @param mode either FORCE_RELOAD or MAY_READ_FROM_CACHE
218+ *
219+ * @return an error message, or null on success
220+ */
209221 @ Override
210222 protected String doInBackground (Integer ... mode ) {
211- ParallelFetcher fetcher = null ;
223+ ParallelFetcher < T > fetcher = null ;
212224 try {
213225 try {
214226 ExternalCacheManager .ReadResult r ;
215227 if (mCacheKey == null || mode [0 ] == FORCE_RELOAD ) {
216228 r = new ExternalCacheManager .ReadResult ();
217229 r .needRefresh = true ;
218230 } else {
219- r = mCache .read (mCacheKey );
231+ r = mCache .read (mCacheKey , mMaxCacheStalenessMillis );
220232 }
221233 final boolean hitCache = (r .obj != null );
222234 if (hitCache ) {
223- Log .d (TAG , "Found cache" );
224235 publishProgress (new ListingStatus <T >((T [])r .obj , false ));
225236 }
226237 if (r .needRefresh ) {
227238 ArrayList <T > aggregate = new ArrayList <T >();
228- T [] objs = null ;
229- fetcher = new ParallelFetcher ();
230-
231- final int numStreams = mEnv .numStreams ();
232- for (int i = 0 ; i < numStreams ; ++i ) {
233- objs = fetcher .next ();
239+ fetcher = new ParallelFetcher <T >(mEnv );
240+ while (fetcher .hasNext ()) {
241+ T [] objs = fetcher .next ();
234242 if (objs != null ) {
235243 for (T obj : objs ) aggregate .add (obj );
236244 if (!hitCache ) {
237245 // Incrementally update the screen as results arrive
238246 publishProgress (new ListingStatus <T >(objs , false ));
239247 } else {
240- // If the screet was already filled with a stale cache,
248+ // If the screen was already filled with a stale cache,
241249 // buffer the new contents until it is complete, so that
242250 // we don't have delete the screen contents midway.
243251 }
244252 }
245253 }
246254 if (fetcher .error () == null ) {
247- objs = aggregate .toArray (objs );
255+ T [] objs = aggregate .toArray (mTmpArray );
248256 if (mCacheKey != null ) mCache .write (mCacheKey , objs );
249257 if (hitCache ) {
250258 publishProgress (new ListingStatus <T >(objs , true ));
0 commit comments