TextView使用自定義HtmlHttpImageGetter實現非同步載入網路圖片,可限制載入圖片數量
阿新 • • 發佈:2019-02-13
import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.text.Html.ImageGetter; import android.view.View; import android.widget.TextView; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.net.URI; import java.net.URL; public class HtmlHttpImageGetter implements ImageGetter { TextView container; URI baseUri; boolean matchParentWidth; static int urlNum = 0; public HtmlHttpImageGetter(TextView textView) { this.container = textView; this.matchParentWidth = false; } public HtmlHttpImageGetter(TextView textView, String baseUrl) { this.container = textView; if (baseUrl != null) { this.baseUri = URI.create(baseUrl); } } public HtmlHttpImageGetter(TextViewtextView, String baseUrl, boolean matchParentWidth) { urlNum = 0; this.container = textView; this.matchParentWidth = matchParentWidth; if (baseUrl != null) { this.baseUri = URI.create(baseUrl); } } public Drawable getDrawable(String source) { UrlDrawable urlDrawable = new UrlDrawable(); urlNum++;//限制詳情頁最多顯示20張圖片 if (urlNum < 20) { // get the actual source ImageGetterAsyncTask asyncTask = new ImageGetterAsyncTask(urlDrawable, this, container, matchParentWidth); asyncTask.execute(source); } // return reference to URLDrawable which will asynchronously load the image specified in the src tag return urlDrawable; } /** * Static inner {@link AsyncTask} that keeps a {@link WeakReference} to the {@link UrlDrawable} * and {@link HtmlHttpImageGetter}. * <p/> * This way, if the AsyncTask has a longer life span than the UrlDrawable, * we won't leak the UrlDrawable or the HtmlRemoteImageGetter. */ private static class ImageGetterAsyncTask extends AsyncTask<String, Void, Drawable> { private final WeakReference<UrlDrawable> drawableReference; private final WeakReference<HtmlHttpImageGetter> imageGetterReference; private final WeakReference<View> containerReference; private String source; private boolean matchParentWidth; private float scale; public ImageGetterAsyncTask(UrlDrawable d, HtmlHttpImageGetter imageGetter, View container, boolean matchParentWidth) { this.drawableReference = new WeakReference<>(d); this.imageGetterReference = new WeakReference<>(imageGetter); this.containerReference = new WeakReference<>(container); this.matchParentWidth = matchParentWidth; } @Override protected Drawable doInBackground(String... params) { source = params[0]; return fetchDrawable(source); } @Override protected void onPostExecute(Drawable result) { if (result == null) { return; } final UrlDrawable urlDrawable = drawableReference.get(); if (urlDrawable == null) { return; } // set the correct bound according to the result from HTTP call urlDrawable.setBounds(0, 0, (int) (result.getIntrinsicWidth() * scale), (int) (result.getIntrinsicHeight() * scale)); // change the reference of the current drawable to the result from the HTTP call urlDrawable.drawable = result; final HtmlHttpImageGetter imageGetter = imageGetterReference.get(); if (imageGetter == null) { return; } // redraw the image by invalidating the container imageGetter.container.invalidate(); // re-set text to fix images overlapping text imageGetter.container.setText(imageGetter.container.getText()); } /** * Get the Drawable from URL */ public Drawable fetchDrawable(String urlString) { try { InputStream is = fetch(urlString); Drawable drawable = Drawable.createFromStream(is, "src"); scale = getScale(drawable); drawable.setBounds(0, 0, (int) (drawable.getIntrinsicWidth() * scale), (int) (drawable.getIntrinsicHeight() * scale)); return drawable; } catch (Exception e) { return null; } } private float getScale(Drawable drawable) { View container = containerReference.get(); if (!matchParentWidth || container == null) { return 1f; } float maxWidth = container.getWidth(); float originalDrawableWidth = drawable.getIntrinsicWidth(); return maxWidth / originalDrawableWidth; } private InputStream fetch(String urlString) throws IOException { URL url; final HtmlHttpImageGetter imageGetter = imageGetterReference.get(); if (imageGetter == null) { return null; } if (imageGetter.baseUri != null) { url = imageGetter.baseUri.resolve(urlString).toURL(); } else { url = URI.create(urlString).toURL(); } return (InputStream) url.getContent(); } } @SuppressWarnings("deprecation") public class UrlDrawable extends BitmapDrawable { protected Drawable drawable; @Override public void draw(Canvas canvas) { // override the draw to facilitate refresh function later if (drawable != null) { drawable.draw(canvas); } } } }