Created
February 4, 2013 18:26
-
-
Save sayan1886/4708531 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// LICENSE: USE IT IF YOU NEED IT, BUT PLEASE MENTION AT LEAST MY NAME, THANKS! | |
// (Juraj Suchán, [email protected]) | |
// | |
// PREFACE: | |
// So i've been building client application for one local "closed community" | |
// nyx.cz for year and a half where the displayed content is standard html code. | |
// | |
// There is Html.fromHtml to the rescue for that! But unfortunatelly, anyone who tried it | |
// have to deal with custom Html.ImageGetter implementation. | |
// This interface contains only one method, with only one paramter (url) and it's completelly | |
// "impossibru" to make it asynchronous anyhow. | |
// Not to mention, if you want to use it in application targeted to HC/ICS and higher, | |
// the NetworkOnMainThreadException will be thrown! | |
// | |
// Here is my workaround (please note that this is snippet rather than full solution): | |
// The first Html.ImageGetter implementation in the getDrawable method | |
// fires of AsyncTask to get the image from specified source and stores it in cache. | |
// Return value for this method is just drawable placeholder (empty image or so). | |
// The second Html.ImageGetter implementation takes the loaded drawable from cache.. | |
// I have this code inside custom list adapter and it may looks like this: | |
// TL;DR we need two imageGetter implementations, one for imageDownloading (igcacher) and one for image drawing from cache (igfromcache) | |
// - when the task from first imageGetter (igcacher) finishes, it sets the resulting drawable to the cache | |
// - apply the second imageGetter (igfromcache) in task onPostExecute, and you're done. | |
// - the textView will redraw correctly because of new calling "setText". | |
//... | |
static final Map<String, WeakReference<Drawable>> mDrawableCache = Collections.synchronizedMap(new WeakHashMap<String, WeakReference<Drawable>>()); | |
//... | |
private Drawable mDefaultDrawable; | |
private Executor mExecutor = Executors.newSingleThreadExecutor(); | |
//... | |
Html.ImageGetter igfromcache = new Html.ImageGetter() { // this is the second imageGetter implementation we need | |
public Drawable getDrawable(String source) { | |
if (!mDrawableCache.containsKey(source)) { | |
return null; | |
} | |
return mDrawableCache.get(source).get(); // the image has been already downloaded and it's stored in cache, right? | |
} | |
} | |
//... | |
final String message = "some html content with image tasks"; | |
final TextView textView = (TextView)findViewById(R.id.discussion_message_tv); | |
Html.ImageGetter igcacher = new Html.ImageGetter() { // this is first imageGetter implementation we need | |
public Drawable getDrawable(String source) { | |
ImageDownloadData imageDownloadData = new ImageDownloadData(source, message, textView); | |
ImageDownloadAsyncTask imageDownloadTask = new ImageDownloadAsyncTask(imageDownloadData); | |
imageDownloadTask.executeOnExecutor(mExecutor, null); // go for it online! | |
return mDefaultDrawable; // this is placeholder image taken from resources. | |
} | |
}; | |
textView.setText(Html.fromHtml(message, igcacher, null)); // the trick starts here, spinoff caching image getter. | |
//... | |
class ImageDownloadData { | |
private String imageSource; | |
private String message; | |
private TextView textView; | |
public ImageDownloadData(String imageSource, String message, TextView textView) { | |
this.imageSource = imageSource; | |
this.message = message; | |
this.textView = textView; | |
} | |
public String getImageSource() { | |
return imageSource; | |
} | |
public String getMessage() { | |
return message; | |
} | |
public TextView getTextView() { | |
return textView; | |
} | |
} | |
//... | |
class ImageDownloadAsyncTask extends AsyncTask<Void, Void, Drawable> { | |
private ImageDownloadData imageDownloadData; | |
public ImageDownloadAsyncTask(ImageDownloadData imageDownloadData) { | |
this.imageDownloadData = imageDownloadData; | |
} | |
@Override | |
protected Drawable doInBackground(Void... params) { | |
Drawable drawable = null; | |
/* | |
code for downloading bitmap is not required here, do it by yourself, | |
remember, the uri for it is in imageDownloadData.getImageSource() ! | |
*/ | |
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); | |
return drawable; | |
} | |
@Override | |
protected void onPostExecute(Drawable drawable) { | |
// put the downloaded drawable into the cache (so the second image getter can access it) | |
if (!mDrawableCache.containsKey(imageDownloadData.getSource())) { | |
mDrawableCache.put(imageDownloadData.getSource(), new WeakReference<Drawable>(drawable)); | |
} | |
TextView textView = imageDownloadData.getTextView(); | |
String message = imageDownloadData.getMessage(); | |
// this does the trick, we need to set the message/text again, but with | |
// different imageGetter (the second one) imeplementation ! | |
textView.setText(MyHtml.fromHtml(content, igfromcache, null)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment