2016-05-14 4 views
0

Говорят, что у меня есть:Какой самый быстрый способ передать изображение между двумя видами деятельности?

Activity activity1 содержащий ImageView imageView1

и

Activity деятельности2 содержащий ImageView imageView2,

и у меня есть строка URL, указывающий на изображение (кэшируются Picasso) , который я уже загрузил в imageView1. Как запустить Activitiy2 и загрузить одно и то же изображение в ImageView2 самым быстрым способом?

В настоящее время я вызываю Picasso.load().into() по URL-адресу, как только начинается действие. Это быстро, но я ищу что-то быстрее.

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

Любое предложение было бы действительно оценено.

ответ

2

Пикассо загружает полное изображение и сохраняет исходное изображение в диске/памяти. Предположим, что размер оригинального изображения был 800x800, и вы пытаетесь загрузить это изображение в представление с размером: 100x100, тогда Picasso займет некоторое время для повторной калибровки. Возможно, вы захотите дать Glide [1] попытку. Glide имеет возможность кэшировать как изображения с размерами, так и исходное изображение. (check Glide # diskCachingStratedgy)

Кроме того, с помощью Picasso, если вы используете .noFade(), изображение может показаться загруженным немного быстрее.

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

+0

. Найденный метод .noFade() был именно тем, что я искал, спасибо! – Matteo

1

Я думаю, что это уже достаточно быстро. Picasso просто получает его из кэша общей памяти, где он хранится как готовый к использованию растровый рисунок. Это быстрее, чем использование aim.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(); 
     } 
    } 

После создания над тремя класами SES вам просто нужно загрузить изображение в 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

Смежные вопросы