I have this multiple calls to AsyncTask that I would like to convert to RxJava. The AsyncTask code works, but I would just like to explore how to do this in RxJava?
(By the way, I know the title sucks)
What it does:
- Loop through MyImageButton (which is just a POJO, not extending ImageButton) list
- On each MyImageButton, get its current bitmap (through getDrawable())
- Get the icon from a URL.
- On combine the two images BitmapUtils.combine(...);
- Assign this newly combined bitmap to an ImageButton
How do I convert this to RxJava:
for (MyImageButton myImageButton: myImageButtons) {
final ImageButton imageButton = (ImageButton) findViewById(myImageButton.getImageButtonResId()); //getImageButtonResId holds a reference to some ImageButton
final Bitmap bitmap = ((BitmapDrawable) imageButton.getDrawable()).getBitmap();
new BindImageTask(imageButton, bitmap, myImageButton.getIconUrl()).execute();
}
Here's the BindImageTask:
private class BindImageTask extends AsyncTask<Void, Void, Bitmap> {
private WeakReference<Bitmap> srcBitmapWeakReference;
private WeakReference<ImageButton> imageButtonWeakReference;
private String dstIconUrl;
BindImageTask(ImageButton imageButton, Bitmap srcBitmap, String dstIconUrl) {
srcBitmapWeakReference = new WeakReference<>(srcBitmap);
imageButtonWeakReference = new WeakReference<>(imageButton);
this.dstIconUrl = dstIconUrl;
}
@Override
protected Bitmap doInBackground(Void... params) {
Bitmap srcBitmap = srcBitmapWeakReference.get();
if (srcBitmap == null) return null;
Bitmap dstBitmap = ImageLoader.getInstance().loadImageSync(dstIconUrl, new ImageSize(60, 60));
if (dstBitmap == null) {
return null;
}
return BitmapUtils.combineImage(srcBitmap, dstBitmap, PorterDuff.Mode.DST_OVER);
}
@Override
protected void onPostExecute(Bitmap resultBitmap) {
super.onPostExecute(resultBitmap);
ImageButton imageButton = imageButtonWeakReference.get();
if (imageButton != null && resultBitmap != null) {
imageButton.setImageBitmap(resultBitmap);
}
}
}
Now I tried to use RxJava on this and, I produced this bad use of RxJava (it works, but I know there's a better way):
Observable<MyImageButton> myImageButtonObservable = Observable.from(myImageButtons);
myImageButtonObservable
.map(new Func1<MyImageButton, MyImageButton>() {
@Override
public MyImageButton call(MyImageButton myImageButton) {
final ImageButton imageButton = (ImageButton) findViewById(myImageButton.getDialButtonResId());
final Bitmap srcBitmap = ((BitmapDrawable) imageButton.getDrawable()).getBitmap();
final Bitmap dstBitmap = ImageLoader.getInstance().loadImageSync(myImageButton.getIcon(), new ImageSize(60, 60));
final Bitmap newBitmap = BitmapUtils.combineImage(srcBitmap, dstBitmap, PorterDuff.Mode.DST_OVER);
ImageLoader.getInstance().getMemoryCache().put(myImageButton.getIconUrl() + "_compound", newBitmap);
return myImageButton;
}
})
.onErrorReturn(new Func1<Throwable, MyImageButton>() {
@Override
public MyImageButton call(Throwable throwable) {
return null;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<MyImageButton>() {
@Override
public void call(MyImageButton myImageButton) {
if(myImageButton == null) {
return;
}
final ImageButton imageButton = (ImageButton) findViewById(myImageButton.getDialButtonResId());
imageButton.setImageBitmap(ImageLoader.getInstance().getMemoryCache().get(myImageButton.getIconUrl() + "_compound"));
}
});
What I wanted to happen is:
- Not having to save the newly combined image into the ImageLoader's cache.
- On the subscribe callback I want to have references to both this new bitmap AND reference to MyImageButton so that I can just do a simple myImageButton.setImageBitmap(newBitmap).
What I don't want:
- To have a bitmap reference inside the MyImageButton class (since I have to serialize it later).