📜 ⬆️ ⬇️

Asynchronous loading of pictures in TextView

It's no secret that TextView in Android supports HTML tags. The tag is supported among them, and the ImageGetter class is used for its processing. And if there are no problems with displaying local graphic files, then when trying to programmatically load a remote drawing into TextView, we get a NetworkOnMainThreadException on Android version 3.0 and higher. As it turned out, there is little in the search engines for solving this problem, and far from all of the proposed solutions are workable. However, a working solution exists.
The solution is to reinstall Spanned again in TextView after loading the picture. Uploaded images will be cached so as not to load them every time we display our field (your implementation may be different). Thus, we need to create two implementations of our ImageGetter:

static final Map<String, WeakReference<Drawable>> mDrawableCache = Collections.synchronizedMap(new WeakHashMap<String, WeakReference<Drawable>>()); @Override public void onCreate(Bundle savedInstanceState) { //... //  ImageGetter Html.ImageGetter igLoader = new Html.ImageGetter() { public Drawable getDrawable(String source) { //    ,          if (mDrawableCache.containsKey(source)) return mDrawableCache.get(source).get(); //  ,     new ImageDownloadAsyncTask(source, message, messageView).execute(); //      return new BitmapDrawable(getResources()); } }; //     messageView.setText(Html.fromHtml(message, igLoader, null)); } //  ImageGetter. //   ,    Html.ImageGetter igCached = new Html.ImageGetter() { public Drawable getDrawable(String source) { //      if (mDrawableCache.containsKey(source)) return mDrawableCache.get(source).get(); return null; } }; 


Now, we define our class from AsyncTask, which will deal directly with downloading the image:
')
 class ImageDownloadAsyncTask extends AsyncTask<Void, Void, Void> { private String source; private String message; private TextView textView; public ImageDownloadAsyncTask(String source, String message, TextView textView) { this.source = source; this.message = message; this.textView = textView; } @Override protected Void doInBackground(Void... params) { if (!mDrawableCache.containsKey(source)) { try { //     URL url = new URL(source); URLConnection connection = url.openConnection(); InputStream is = connection.getInputStream(); Drawable drawable = Drawable.createFromStream(is, "src"); //  ,    , //       // . /* Bitmap bmp = BitmapFactory.decodeStream(is); DisplayMetrics dm = MainActivity.this.getResources().getDisplayMetrics(); bmp.setDensity(dm.densityDpi); Drawable drawable=new BitmapDrawable(MainActivity.this.getResources(),bmp); */ is.close(); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); mDrawableCache.put(source, new WeakReference<Drawable>( drawable)); } catch (MalformedURLException e) { e.printStackTrace(); } catch (Throwable t) { t.printStackTrace(); } } return null; } @Override protected void onPostExecute(Void result) { //     textView.setText(Html.fromHtml(message, igCached, null)); } } 


Of course, you need to remember to set in the manifest the permission android.permission.INTERNET .

Source / Entire Project

Source: https://habr.com/ru/post/155879/


All Articles