2014-09-29 50 views
0

我ImageCache的ListView滚动慢,甚至使用backThread载入图像

public class ImageCache { 
    private static ImageCache instance; 
    private Context mContext; 
    private HashMap<Chat, Boolean> isContain = new HashMap<Chat, Boolean>(); 
    private static Bitmap defaultBitmap; 

    private int loginId; 
    private WorkQueue workQueue; 
    private LruCache<Chat, Bitmap> cache = new LruCache<Chat, Bitmap>(
      (int) getMaxSize()) { 
     @SuppressLint("NewApi") 
     protected int sizeOf(Chat key, Bitmap value) { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { 
       return value.getByteCount(); 
      } else { 
       return value.getRowBytes() * value.getHeight(); 
      } 
     } 

     protected Bitmap create(Chat ChatKey) { 
      if (Looper.myLooper() == Looper.getMainLooper()) { 
       Log.i("getView", "main thread"); 
       return null; 
      } 
      Log.i("getView", "image cache"); 
      // if(Thread.currentThread().getName().equals("main")){ 
      // return null; 
      // } 
      Bitmap bitmap = null; 
      if (ChatKey.getMsgType() == Chat.TYPE_IMAGE) { 
       bitmap = getImageThumbnail(ChatKey); 
       synchronized (isContain) { 
        isContain.put(ChatKey, true); 
       } 
       return bitmap; 
      } 
      bitmap = getVideoThumbnail(ChatKey); 
      synchronized (isContain) { 
       isContain.put(ChatKey, true); 
      } 
      return bitmap; 
     } 

     @Override 
     protected void entryRemoved(boolean evicted, Chat key, Bitmap oldValue, 
       Bitmap newValue) { 
      super.entryRemoved(evicted, key, oldValue, newValue); 
      synchronized (isContain) { 
       isContain.put(key, false); 
      } 
      oldValue.recycle(); 
      if (evicted) { 
      } 
     } 
    }; 

    private Bitmap getVideoThumbnail(Chat chat) { 
     if (chat.isPending()) { 
      return getVideoThumbnail(chat.getFilePath()); 
     } 
     if (loginId == chat.getSenderID()) { 
      DataBaseHandler baseHandler = new DataBaseHandler(mContext); 
      String fIlePath = baseHandler.getSentMsgFIlePath(chat.getMsgID()); 
      if (fIlePath != null) { 
       return getVideoThumbnail(fIlePath); 
      } 
     } 
     File file = new File(Util.videoDir, chat.getMsgID() 
       + Util.getExtension(chat.getChatContent())); 
     if (!file.exists()) { 
      file = new File(Util.thumbnails, chat.getMsgID() + ""); 
      if (!file.exists()) { 
       Util.downloadThumbnail(chat); 
       if (!file.exists()) { 
        return null; 
       } 
      } 
      return BitmapFactory.decodeFile(file.getAbsolutePath()); 
     } 
     return getVideoThumbnail(file.getAbsolutePath()); 
    } 
    private Bitmap getImageThumbnail(Chat chat) { 
     if (chat.isPending()) { 
      return getImageThumbnail(chat.getFilePath()); 
     } 
     if (loginId == chat.getSenderID()) { 

      DataBaseHandler baseHandler = new DataBaseHandler(mContext); 
      String fIlePath = baseHandler.getSentMsgFIlePath(chat.getMsgID()); 
      if (fIlePath != null) { 
       return getImageThumbnail(fIlePath); 
      } 
     } 
     File file = new File(Util.imageDir, chat.getMsgID() + ""); 
     if (!file.exists()) { 

      file = new File(Util.thumbnails, chat.getMsgID() + ""); 
      if (!file.exists()) { 
       Util.downloadThumbnail(chat); 
       if (!file.exists()) { 
        return null; 
       } 
      } 
      Bitmap image = BitmapFactory.decodeFile(file.getAbsolutePath()); 

      return image; 
     } 
     return getImageThumbnail(file.getAbsolutePath()); 
    } 

    private Bitmap getImageThumbnail(String imagePath) { 
     BitmapFactory.Options options = new Options(); 
     options.inPreferredConfig = Config.RGB_565; 
     Bitmap image = null; 
     if (imagePath == null) { 
      return null; 
     } 
     Cursor cursor = mContext.getContentResolver().query(
       MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
       new String[] { MediaStore.Video.Media._ID }, 
       new String(MediaStore.Video.Media.DATA + "=?"), 
       new String[] { imagePath }, null); 

     if (cursor.getCount() > 0) { 

      cursor.moveToFirst(); 
      image = MediaStore.Images.Thumbnails.getThumbnail(
        mContext.getContentResolver(), cursor.getInt(0), 
        Thumbnails.MICRO_KIND, options); 
      cursor.close(); 
      return image; 
     } 
     cursor.close(); 
     return null; 
    } 


    private Bitmap getVideoThumbnail(String imagePath) { 
     Bitmap image = null; 
     BitmapFactory.Options options = new Options(); 
     options.inPreferredConfig = Config.RGB_565; 
     Cursor cursor = mContext.getContentResolver().query(
       MediaStore.Video.Media.EXTERNAL_CONTENT_URI, 
       new String[] { MediaStore.Video.Media._ID }, 
       new String(MediaStore.Video.Media.DATA + "=?"), 
       new String[] { imagePath }, null); 
     if (cursor.getCount() > 0) { 
      cursor.moveToFirst(); 
      image = MediaStore.Video.Thumbnails.getThumbnail(
        mContext.getContentResolver(), cursor.getInt(0), 
        Thumbnails.MICRO_KIND, null); 
      cursor.close(); 
      return image; 
     } 
     cursor.close(); 
     return null; 
    } 

    private ImageCache(Context context) { 
     mContext = context.getApplicationContext(); 
     loginId = Util.getSharedPref(mContext).getInt(C.LOGIN_USER_ID, -1); 
     defaultBitmap = BitmapFactory.decodeResource(mContext.getResources(), 
       R.drawable.image); 
     workQueue = WorkQueue.getInstance(context); 
    } 

    public static ImageCache getInstance(Context context) { 
     if (instance == null) { 
      instance = new ImageCache(context); 
     } 
     return instance; 
    } 

    private long getMaxSize() { 
     return Runtime.getRuntime().totalMemory()/4; 
    } 

    public boolean isBitmapLoaded(Chat key) { 
     synchronized (isContain) { 
      if (isContain.get(key) == null) { 
       return false; 
      } 
      return isContain.get(key); 
     } 
    } 

    public void getImage(Chat key){ 
     cache.get(key); 
    } 
    public Bitmap getBitmap(Chat key) { 
     if (isBitmapLoaded(key)) { 
      return cache.get(key); 
     } 
     workQueue.addRequest(key); 
     return defaultBitmap; 
    } 

    public void remove(Chat key) { 
     cache.remove(key); 
     isContain.put(key, false); 
    } 

    public void evictAll() { 
     cache.evictAll(); 
    } 
    } 

我的工作队列

 public class WorkQueue { 
    private final int MAX_THREAD = 1; 
    private WorkerThread[] threads; 
    private ArrayList<Chat> queue; 
    private static WorkQueue instance; 
    private ImageCache imageCache; 
    private ImageLoadListner imageLoadListner; 

    private WorkQueue(Context context) { 
     threads = new WorkerThread[MAX_THREAD]; 

     for (int i = 0; i < MAX_THREAD; i++) { 
      threads[i] = new WorkerThread(); 
      threads[i].start(); 
     } 
     queue = new ArrayList<Chat>(); 
    } 

    public void setImageCache(ImageCache imageCache){ 
     this.imageCache=imageCache; 
    } 
    public static WorkQueue getInstance(Context context) { 
     if (instance == null) { 
      instance = new WorkQueue(context); 
     } 
     return instance; 
    } 

    public void addRequest(Chat key) { 
     synchronized (queue) { 
      if(queue.contains(key)){ 
       return; 
      } 
      if(queue.size()==20){ 
       queue.remove(0); 
      } 
      queue.add(key); 
      queue.notify(); 
     } 
    } 

    public void setImageLoadListner(ImageLoadListner listner) { 
     this.imageLoadListner = listner; 
    } 

    private class WorkerThread extends Thread { 
     @Override 
     public void run() { 
      super.run(); 
      setName("Background"); 
      synchronized (queue) { 
       if (queue.size() == 0) { 
        try { 
         queue.wait(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
      while (queue.size() > 0) { 
       Chat chat = queue.get(0); 
       imageCache.getImage(chat); 
       imageLoadListner.onImageLoad(chat); 
       synchronized (queue) { 
        queue.remove(0); 
        if (queue.size() == 0) { 
         try { 
          queue.wait(); 
         } catch (InterruptedException e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      } 
     } 
    } 

} 

我打电话从适配器的getView()getBitmap(键),当图像通知适配器通过调用来自workqueqe的适配器的onIMageLoad()加载。调用imagecache从backthread创建即使然后LOG在imageCache的create()中也是由于backThread上的位图创建而导致print和listView滚动速度很慢。

+0

从代码调用'的getImage()'这就叫LruCache'GET'这在一般不会加载任何文件系统或数据库。我认为你仍然可以加载或解码UI线程上的图像。打开严格模式并阅读日志。此外,扩展'LruCache'肯定会破坏KISS和S从SOLID规则 – 2014-09-29 13:47:16

+0

或者,只是不要浪费你的时间再次由几个非常有才华的开发人员再次完成某些事情,而只是使用一个库来实现它,例如我的首选http://square.github.io/picasso/简单为'Picasso.with(context).load(url).into(imgView);' – Budius 2014-09-29 15:19:25

回答

0

Hanish U应该使用LinkedList WorkQueue为private ArrayList<Chat> queue;,因为在链接列表中添加或删除的速度非常快,并且将图像ID保存在Chat对象中,因为您正在为获取Thumbnil首先进行双重工作。大拇指。 和视频上面我看到后台线程(的WorkerThread)U可以直接使用而无需更改代码

ThumbnailUtils.public static Bitmap createVideoThumbnail (String filePath, int kind) 
+0

Thanx为您的建议。我真的觉得它很有帮助。 – user3289808 2014-10-09 04:03:19