2
2
3
3
import android .app .Activity ;
4
4
import android .content .Context ;
5
+ import android .content .res .Resources ;
6
+ import android .graphics .Bitmap ;
7
+ import android .graphics .BitmapFactory ;
5
8
import android .graphics .Color ;
9
+ import android .graphics .drawable .BitmapDrawable ;
10
+ import android .graphics .drawable .Drawable ;
11
+ import android .os .AsyncTask ;
6
12
import android .support .annotation .ColorRes ;
7
13
import android .support .v7 .widget .CardView ;
8
14
import android .support .v7 .widget .RecyclerView ;
15
21
import org .buildmlearn .toolkit .R ;
16
22
import org .buildmlearn .toolkit .model .Template ;
17
23
24
+ import java .lang .ref .WeakReference ;
25
+
18
26
/**
19
27
* @brief Adapter used for showing Templates available in the toolkit
20
28
* <p>
@@ -32,6 +40,35 @@ public TemplateAdapter(Context context) {
32
40
this .context = context ;
33
41
}
34
42
43
+ public static boolean cancelPotentialWork (int data , ImageView imageView ) {
44
+ final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask (imageView );
45
+
46
+ if (bitmapWorkerTask != null ) {
47
+ final int bitmapData = bitmapWorkerTask .data ;
48
+ // If bitmapData is not yet set or it differs from the new data
49
+ if (bitmapData == 0 || bitmapData != data ) {
50
+ // Cancel previous task
51
+ bitmapWorkerTask .cancel (true );
52
+ } else {
53
+ // The same work is already in progress
54
+ return false ;
55
+ }
56
+ }
57
+ // No task associated with the ImageView, or an existing task was cancelled
58
+ return true ;
59
+ }
60
+
61
+ private static BitmapWorkerTask getBitmapWorkerTask (ImageView imageView ) {
62
+ if (imageView != null ) {
63
+ final Drawable drawable = imageView .getDrawable ();
64
+ if (drawable instanceof AsyncDrawable ) {
65
+ final AsyncDrawable asyncDrawable = (AsyncDrawable ) drawable ;
66
+ return asyncDrawable .getBitmapWorkerTask ();
67
+ }
68
+ }
69
+ return null ;
70
+ }
71
+
35
72
public void setOnClickListener (ViewHolder .SetOnClickListener clickListener ) {
36
73
this .listener = clickListener ;
37
74
}
@@ -67,12 +104,18 @@ public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
67
104
68
105
vh .getTitle ().setText (template .getTitle ());
69
106
vh .getDescription ().setText (template .getDescription ());
70
- vh .getImage ().setImageResource (template .getImage ());
71
107
72
108
int color = colors [position % colors .length ].getColor ();
73
109
vh .getCardView ().setCardBackgroundColor (color );
74
110
vh .setItemClickListener (listener );
75
111
112
+ if (cancelPotentialWork (template .getImage (), vh .getImage ())) {
113
+ final BitmapWorkerTask task = new BitmapWorkerTask (context , vh .getImage ());
114
+ final AsyncDrawable asyncDrawable =
115
+ new AsyncDrawable (context .getResources (), null , task );
116
+ vh .getImage ().setImageDrawable (asyncDrawable );
117
+ task .execute (template .getImage ());
118
+ }
76
119
}
77
120
78
121
@ Override
@@ -170,4 +213,94 @@ public interface SetOnClickListener {
170
213
void onItemClick (int position );
171
214
}
172
215
}
216
+
217
+ static class AsyncDrawable extends BitmapDrawable {
218
+ private final WeakReference <BitmapWorkerTask > bitmapWorkerTaskReference ;
219
+
220
+ public AsyncDrawable (Resources res , Bitmap bitmap ,
221
+ BitmapWorkerTask bitmapWorkerTask ) {
222
+ super (res , bitmap );
223
+ bitmapWorkerTaskReference =
224
+ new WeakReference <BitmapWorkerTask >(bitmapWorkerTask );
225
+ }
226
+
227
+ public BitmapWorkerTask getBitmapWorkerTask () {
228
+ return bitmapWorkerTaskReference .get ();
229
+ }
230
+ }
231
+
232
+ class BitmapWorkerTask extends AsyncTask <Integer , Void , Bitmap > {
233
+ private final WeakReference <ImageView > imageViewReference ;
234
+ private int data = 0 ;
235
+ private Context mContext ;
236
+
237
+ public BitmapWorkerTask (Context context , ImageView imageView ) {
238
+ // Use a WeakReference to ensure the ImageView can be garbage collected
239
+ mContext = context ;
240
+ imageViewReference = new WeakReference <ImageView >(imageView );
241
+ }
242
+
243
+ // Decode image in background.
244
+ @ Override
245
+ protected Bitmap doInBackground (Integer ... params ) {
246
+ data = params [0 ];
247
+ return decodeSampledBitmapFromResource (context .getResources (), data , 141 , 180 );
248
+ }
249
+
250
+ // Once complete, see if ImageView is still around and set bitmap.
251
+ @ Override
252
+ protected void onPostExecute (Bitmap bitmap ) {
253
+ if (isCancelled ()) {
254
+ bitmap = null ;
255
+ }
256
+
257
+ if (imageViewReference != null && bitmap != null ) {
258
+ final ImageView imageView = imageViewReference .get ();
259
+ final BitmapWorkerTask bitmapWorkerTask =
260
+ getBitmapWorkerTask (imageView );
261
+ if (this == bitmapWorkerTask && imageView != null ) {
262
+ imageView .setImageBitmap (bitmap );
263
+ }
264
+ }
265
+ }
266
+
267
+ public Bitmap decodeSampledBitmapFromResource (Resources res , int resId ,
268
+ int reqWidth , int reqHeight ) {
269
+
270
+ // First decode with inJustDecodeBounds=true to check dimensions
271
+ final BitmapFactory .Options options = new BitmapFactory .Options ();
272
+ options .inJustDecodeBounds = true ;
273
+ BitmapFactory .decodeResource (res , resId , options );
274
+
275
+ // Calculate inSampleSize
276
+ options .inSampleSize = calculateInSampleSize (options , reqWidth , reqHeight );
277
+
278
+ // Decode bitmap with inSampleSize set
279
+ options .inJustDecodeBounds = false ;
280
+ return BitmapFactory .decodeResource (res , resId , options );
281
+ }
282
+
283
+ public int calculateInSampleSize (
284
+ BitmapFactory .Options options , int reqWidth , int reqHeight ) {
285
+ // Raw height and width of image
286
+ final int height = options .outHeight ;
287
+ final int width = options .outWidth ;
288
+ int inSampleSize = 1 ;
289
+
290
+ if (height > reqHeight || width > reqWidth ) {
291
+
292
+ final int halfHeight = height / 2 ;
293
+ final int halfWidth = width / 2 ;
294
+
295
+ // Calculate the largest inSampleSize value that is a power of 2 and keeps both
296
+ // height and width larger than the requested height and width.
297
+ while ((halfHeight / inSampleSize ) >= reqHeight
298
+ && (halfWidth / inSampleSize ) >= reqWidth ) {
299
+ inSampleSize *= 2 ;
300
+ }
301
+ }
302
+
303
+ return inSampleSize ;
304
+ }
305
+ }
173
306
}
0 commit comments