2016-05-14 82 views
0

說,我有:兩種活動之間傳遞圖像的最快方式是什麼?

Activity含有ImageView imageView1活性1

Activity含有ImageView imageView2,活性2

和我有一個字符串的URL指向一個圖像(由Picasso緩存) ,我已經加載到imageView1。 如何啓動Activitiy2並以最快的方式將相同的圖像加載到ImageView2中?

目前,我打電話Picasso.load().into()上的URL一旦活動啓動。這很快,但我正在尋找更快的東西。

Picasso.with(mContext) 
     .load(myUrl) 
     .into(imageView2); 

任何建議將非常感激。

回答

2

畢加索下載完整的圖像,並在磁盤/存儲保存原始圖像。假設原始圖像尺寸爲800x800,並且您試圖將此圖像加載到尺寸爲100x100的視圖中,那麼畢加索將需要一些時間來重新調整尺寸。 你可能想試試Glide [1]。 Glide可以同時緩存重新調整大小的圖像和原始圖像。 (檢查Glide#diskCachingStratedgy)

另外,如果使用.noFade()選項,那麼在Picasso中,圖像可能會加載得更快。

[1] https://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en

+0

找到.noFade()方法正是我所期待的,謝謝! – Matteo

1

我認爲它已經夠快了。畢加索從共享內存緩存中獲取它,並將其存儲爲可以使用的位圖。它比使用intent.putExtra(「image」.bitmapByteArray)或使用具有解碼或編碼位圖的文件更快。

1

您需要創建三個類用於將圖像存儲在緩存中,並且加載圖像速度更快。 1. ImageLoader.java 2. FileCache.java 3. MemoryCache.java

ImageLoader.java

package com.thefinal3.Camera; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.util.Collections; 
import java.util.Map; 
import java.util.WeakHashMap; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

import android.app.Activity; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.widget.ImageView; 

import com.thefinal3.R; 
import com.thefinal3.Utils.Utils; 

/** 
* Created by Akash patel on 03-05-2016. 
*/ 
public class ImageLoader { 

    MemoryCache memoryCache=new MemoryCache(); 
    FileCache fileCache; 
    private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>()); 
    ExecutorService executorService; 

    public ImageLoader(Context context){ 
     fileCache=new FileCache(context); 
     executorService=Executors.newFixedThreadPool(5); 
    } 

    final int stub_id= R.drawable.ic_no_image; 
    public void DisplayImage(String url, ImageView imageView) 
    { 
     imageViews.put(imageView, url); 
     Bitmap bitmap=memoryCache.get(url); 
     if(bitmap!=null) 
      imageView.setImageBitmap(bitmap); 
     else 
     { 
      queuePhoto(url, imageView); 
      imageView.setImageResource(stub_id); 
     } 
    } 

    private void queuePhoto(String url, ImageView imageView) 
    { 
     PhotoToLoad p=new PhotoToLoad(url, imageView); 
     executorService.submit(new PhotosLoader(p)); 
    } 

    private Bitmap getBitmap(String url) 
    { 
     File f=fileCache.getFile(url); 

     //from SD cache 
     Bitmap b = decodeFile(f); 
     if(b!=null) 
      return b; 

     //from web 
     try { 
      Bitmap bitmap=null; 
      URL imageUrl = new URL(url); 
      HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection(); 
      conn.setConnectTimeout(30000); 
      conn.setReadTimeout(30000); 
      conn.setInstanceFollowRedirects(true); 
      InputStream is=conn.getInputStream(); 
      OutputStream os = new FileOutputStream(f); 
      Utils.CopyStream(is, os); 
      os.close(); 
      bitmap = decodeFile(f); 
      return bitmap; 
     } catch (Throwable ex){ 
      ex.printStackTrace(); 
      if(ex instanceof OutOfMemoryError) 
       memoryCache.clear(); 
      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*=2; 
      } 

      //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; 
     } 
    } 

    class PhotosLoader implements Runnable { 
     PhotoToLoad photoToLoad; 
     PhotosLoader(PhotoToLoad photoToLoad){ 
      this.photoToLoad=photoToLoad; 
     } 

     @Override 
     public void run() { 
      if(imageViewReused(photoToLoad)) 
       return; 
      Bitmap bmp=getBitmap(photoToLoad.url); 
      memoryCache.put(photoToLoad.url, bmp); 
      if(imageViewReused(photoToLoad)) 
       return; 
      BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad); 
      Activity a=(Activity)photoToLoad.imageView.getContext(); 
      a.runOnUiThread(bd); 
     } 
    } 

    boolean imageViewReused(PhotoToLoad photoToLoad){ 
     String tag=imageViews.get(photoToLoad.imageView); 
     if(tag==null || !tag.equals(photoToLoad.url)) 
      return true; 
     return false; 
    } 

    //Used to display bitmap in the UI thread 
    class BitmapDisplayer implements Runnable 
    { 
     Bitmap bitmap; 
     PhotoToLoad photoToLoad; 
     public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;} 
     public void run() 
     { 
      if(imageViewReused(photoToLoad)) 
       return; 
      if(bitmap!=null) 
       photoToLoad.imageView.setImageBitmap(bitmap); 
      else 
       photoToLoad.imageView.setImageResource(stub_id); 
     } 
    } 

    public void clearCache() { 
     memoryCache.clear(); 
     fileCache.clear(); 
    } 

} 

FileCache.java

package com.thefinal3.Camera; 

import android.content.Context; 

import java.io.File; 

/** 
* Created by Akash patel on 03-05-2016. 
*/ 
public class FileCache { 

    private File cacheDir; 

    public FileCache(Context context){ 
     //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(),"TTImages_cache"); 
     else 
      cacheDir=context.getCacheDir(); 
     if(!cacheDir.exists()) 
      cacheDir.mkdirs(); 
    } 

    public File getFile(String url){ 
     //I identify images by hashcode. Not a perfect solution, good for the demo. 
     String filename=String.valueOf(url.hashCode()); 
     //Another possible solution (thanks to grantland) 
     //String filename = URLEncoder.encode(url); 
     File f = new File(cacheDir, filename); 
     return f; 

    } 

    public void clear(){ 
     File[] files=cacheDir.listFiles(); 
     if(files==null) 
      return; 
     for(File f:files) 
      f.delete(); 
    } 

} 

MemoryCache.java

package com.thefinal3.Camera; 
    import java.util.Collections; 
    import java.util.Iterator; 
    import java.util.LinkedHashMap; 
    import java.util.Map; 
    import java.util.Map.Entry; 
    import android.graphics.Bitmap; 
    import android.util.Log; 

    public class MemoryCache { 

     private static final String TAG = "MemoryCache"; 
     private Map<String, Bitmap> cache= Collections.synchronizedMap(
       new LinkedHashMap<String, Bitmap>(10, 1.5f, true));//Last argument true for LRU ordering 
     private long size=0;//current allocated size 
     private long limit=1000000;//max memory in bytes 

     public MemoryCache(){ 
      //use 25% of available heap size 
      setLimit(Runtime.getRuntime().maxMemory()/4); 
     } 

     public void setLimit(long new_limit){ 
      limit=new_limit; 
      Log.i(TAG, "MemoryCache will use up to " + limit/1024./1024. + "MB"); 
     } 

     public Bitmap get(String id){ 
      try{ 
       if(!cache.containsKey(id)) 
        return null; 
       //NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78 
       return cache.get(id); 
      }catch(NullPointerException ex){ 
       ex.printStackTrace(); 
       return null; 
      } 
     } 

     public void put(String id, Bitmap bitmap){ 
      try{ 
       if(cache.containsKey(id)) 
        size-=getSizeInBytes(cache.get(id)); 
       cache.put(id, bitmap); 
       size+=getSizeInBytes(bitmap); 
       checkSize(); 
      }catch(Throwable th){ 
       th.printStackTrace(); 
      } 
     } 

     private void checkSize() { 
      Log.i(TAG, "cache size="+size+" length="+cache.size()); 
      if(size>limit){ 
       Iterator<Entry<String, Bitmap>> iter=cache.entrySet().iterator();//least recently accessed item will be the first one iterated 
       while(iter.hasNext()){ 
        Entry<String, Bitmap> entry=iter.next(); 
        size-=getSizeInBytes(entry.getValue()); 
        iter.remove(); 
        if(size<=limit) 
         break; 
       } 
       Log.i(TAG, "Clean cache. New size "+cache.size()); 
      } 
     } 

     public void clear() { 
      try{ 
       //NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78 
       cache.clear(); 
       size=0; 
      }catch(NullPointerException ex){ 
       ex.printStackTrace(); 
      } 
     } 

     long getSizeInBytes(Bitmap bitmap) { 
      if(bitmap==null) 
       return 0; 
      return bitmap.getRowBytes() * bitmap.getHeight(); 
     } 
    } 

創建上述三個分類後你只需要像這樣在imageview中加載圖像:

ImageLoader imageLoader = new ImageLoader(activity); 
      imageLoader.DisplayImage(bean.getPhotoURL(),holder.imgSelectedPhoto); 
+0

謝謝您的回答,我會得到它的眼睛儘快 – Matteo

+0

加載和緩存圖像是一個低級別運行。一般來說,在應用程序中嵌入低級代碼是非常錯誤的。 –

0

你能提供一個「快速」(如0.1秒)的定量測​​量嗎?你可以很容易地做到這一點 -

Intent intent = new Intent(this, NewActivity.class); 
intent.putExtra("BitmapImage", bitmap); 

和檢索它 -

Intent intent = getIntent(); 
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage"); 
+0

正確。問題是我有大量的照片,轉換爲位圖是一個昂貴的過程..我應該嘗試轉換onClick,但這可能會失去我正在尋找的「速度」。 目前我的加載時間約爲2秒,我想呆在0.5 – Matteo

相關問題