如何在Android中处理加载图像
如何在Android中处理加载图像
这个问题已经有了答案:
可能的重复问题:
我已经尝试了几天,但似乎无法理解这个过程。我的应用从服务器访问大量的图片。目前,它被设置为一次加载并显示一张图片。当用户点击下一个按钮时,下一张图片就会被加载并显示。但加载时间有点太长了。有什么方法可以改善下一张图片的加载时间呢?
我一直在尝试线程和AsyncTask。我的想法是将前一张和下一张图像也保留在内存中。当用户点击下一个按钮时,我执行以下操作:
prevImage = currentImage; currentImage = nextImage; nextImage = getBitmapfromURL(urlPath);
nextImage实际上是在AsyncTask或线程中执行的。我遇到的问题是,如果用户在该线程完成之前点击了下一个按钮(它只会显示一个空白图像),那么我不确定是否应该这样做。是否有其他方法可以改善这些图像的加载时间呢?
admin 更改状态以发布 2023年5月22日
这是我从服务器加载图像的类。
package test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.net.URL; import java.util.HashMap; import java.util.Stack; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.widget.ImageView; import com.com.app.R; public class ImageLoader { // the simplest in-memory cache implementation. This should be replaced with // something like SoftReference or BitmapOptions.inPurgeable(since 1.6) private HashMapcache = new HashMap (); private File cacheDir; public ImageLoader(Context context) { // Make the background thead low priority. This way it will not affect // the UI performance photoLoaderThread.setPriority(Thread.NORM_PRIORITY - 1); // Find the dir to save cached images if (android.os.Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED)) cacheDir = new File( android.os.Environment.getExternalStorageDirectory(), "LazyList"); else cacheDir = context.getCacheDir(); if (!cacheDir.exists()) cacheDir.mkdirs(); } final int stub_id = R.drawable.no_image; public void DisplayImage(String url, Activity activity, ImageView imageView) { if (cache.containsKey(url)) imageView.setImageBitmap(cache.get(url)); else { queuePhoto(url, activity, imageView); imageView.setImageResource(stub_id); } } private void queuePhoto(String url, Activity activity, ImageView imageView) { // This ImageView may be used for other images before. So there may be // some old tasks in the queue. We need to discard them. photosQueue.Clean(imageView); PhotoToLoad p = new PhotoToLoad(url, imageView); synchronized (photosQueue.photosToLoad) { photosQueue.photosToLoad.push(p); photosQueue.photosToLoad.notifyAll(); } // start thread if it's not started yet if (photoLoaderThread.getState() == Thread.State.NEW) photoLoaderThread.start(); } private Bitmap getBitmap(String url) { // // I identify images by hashcode. Not a perfect solution, good for // the // // demo. // String filename = String.valueOf(url.hashCode()); // File f = new File(cacheDir, filename); // // // from SD cache // Bitmap b = decodeFile(f); // if (b != null) // return b; // from web try { return new BitmapDrawable(new URL(url).openStream()).getBitmap(); } catch (Exception ex) { ex.printStackTrace(); return null; } } // decodes image and scales it to reduce memory consumption private Bitmap decodeFile(File f) { try { // decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(new FileInputStream(f), null, o); // Find the correct scale value. It should be the power of 2. final int REQUIRED_SIZE = 70; int width_tmp = o.outWidth, height_tmp = o.outHeight; int scale = 1; while (true) { if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE) break; width_tmp /= 2; height_tmp /= 2; scale++; } // decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); } catch (FileNotFoundException e) { } return null; } // Task for the queue private class PhotoToLoad { public String url; public ImageView imageView; public PhotoToLoad(String u, ImageView i) { url = u; imageView = i; } } PhotosQueue photosQueue = new PhotosQueue(); public void stopThread() { photoLoaderThread.interrupt(); } // stores list of photos to download class PhotosQueue { private Stack photosToLoad = new Stack (); // removes all instances of this ImageView public void Clean(ImageView image) { for (int j = 0; j < photosToLoad.size();) { if (photosToLoad.get(j).imageView == image) photosToLoad.remove(j); else ++j; } } } class PhotosLoader extends Thread { public void run() { try { while (true) { // thread waits until there are any images to load in the // queue if (photosQueue.photosToLoad.size() == 0) synchronized (photosQueue.photosToLoad) { photosQueue.photosToLoad.wait(); } if (photosQueue.photosToLoad.size() != 0) { PhotoToLoad photoToLoad; synchronized (photosQueue.photosToLoad) { photoToLoad = photosQueue.photosToLoad.pop(); } Bitmap bmp = getBitmap(photoToLoad.url); cache.put(photoToLoad.url, bmp); if (photoToLoad.url == null) { photoToLoad.url = "http://192.168.0.2/phpdemoprojects/cardsonmobile/uploads/cards/0009.png"; } else { if (((String) photoToLoad.imageView.getTag()) .equals(photoToLoad.url)) { BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad.imageView); Activity a = (Activity) photoToLoad.imageView .getContext(); a.runOnUiThread(bd); } } } if (Thread.interrupted()) break; } } catch (InterruptedException e) { // allow thread to exit } } } PhotosLoader photoLoaderThread = new PhotosLoader(); // Used to display bitmap in the UI thread class BitmapDisplayer implements Runnable { Bitmap bitmap; ImageView imageView; public BitmapDisplayer(Bitmap b, ImageView i) { bitmap = b; imageView = i; } public void run() { if (bitmap != null) imageView.setImageBitmap(bitmap); else imageView.setImageResource(stub_id); } } public void clearCache() { // clear memory cache cache.clear(); // clear SD cache File[] files = cacheDir.listFiles(); for (File f : files) f.delete(); } }