3

Пожалуйста, кто-то добавил много изображений в просмотрщик раньше? У меня есть действие, которое вызывает класс фрагмента для создания фрагментов, содержащих изображения, в viewpager, и этот класс фрагмента содержит методы, которые кэшируют изображение, если оно еще не существует в кэш-памяти, и изменяет размер изображения и позволяет выполнить рисование в asynctask, чтобы уменьшить потребление времени перед задачей ... , но со всеми этими методами, чтобы устранить ошибку из памяти, я все еще имею эту ошибку !!! были два или три дня, теперь пытаясь использовать разные методы, и никто из них не работал ... поэтому любые мысли, пожалуйста!ошибка при ошибке при использовании viewpager + изображение даже при использовании кэш-памяти и асинтетики

Мой код:

import java.lang.ref.WeakReference; 

import android.content.res.Resources; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.drawable.BitmapDrawable; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.util.LruCache; 
import android.util.DisplayMetrics; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ImageView; 


public class ScreenSlidePageFragment extends Fragment { 
    /** 
    * The argument key for the page number this fragment represents. 
    */ 
    public static final String ARG_PAGE = "page"; 
    private LruCache<String, Bitmap> mMemoryCache; 

    /** 
    * The fragment's page number, which is set to the argument value for {@link #ARG_PAGE}. 
    */ 
    ImageView img; 
    int height; 
    int width; 
    private int mPageNumber; 
    private int[] pics = {R.drawable.intro1, R.drawable.intro2,R.drawable.intro3,R.drawable.intro4,R.drawable.intro5,R.drawable.intro6,R.drawable.intro7,R.drawable.intro8, 
      R.drawable.intro9,R.drawable.intro10,R.drawable.intro11,R.drawable.intro12,R.drawable.intro13,R.drawable.intro14,R.drawable.intro15,R.drawable.intro16,R.drawable.intro17,R.drawable.intro18, 
      R.drawable.intro19,R.drawable.intro20,R.drawable.intro21,R.drawable.intro22,R.drawable.intro23,R.drawable.intro24,R.drawable.intro25,R.drawable.intro26,R.drawable.intro27,R.drawable.intro28,R.drawable.intro29,R.drawable.intro30, 
      R.drawable.intro31,R.drawable.intro32,R.drawable.intro33,R.drawable.intro34,R.drawable.intro35,R.drawable.intro36,R.drawable.intro37,R.drawable.intro38,R.drawable.intro39,R.drawable.intro40,R.drawable.intro41,R.drawable.intro42, 
      R.drawable.intro43,R.drawable.intro44,R.drawable.intro45,R.drawable.intro46,R.drawable.intro47,R.drawable.intro48,R.drawable.intro49,R.drawable.intro50,R.drawable.intro51,R.drawable.intro52,R.drawable.intro53,R.drawable.intro54, 
      R.drawable.intro55,R.drawable.intro56,R.drawable.intro57,R.drawable.intro58,R.drawable.intro59,R.drawable.intro60,R.drawable.intro61,R.drawable.intro62,R.drawable.intro63,R.drawable.intro64,R.drawable.intro65,R.drawable.intro66, 
      R.drawable.intro67,R.drawable.intro68,R.drawable.intro69,R.drawable.intro70,R.drawable.intro71,R.drawable.intro72,R.drawable.intro73}; 
    int count=72;//it's the number of the images-1; 


    /** 
    * Factory method for this fragment class. Constructs a new fragment for the given page number. 
    */ 
    public static ScreenSlidePageFragment create(int pageNumber) { 
     ScreenSlidePageFragment fragment = new ScreenSlidePageFragment(); 
     Bundle args = new Bundle(); 
     args.putInt(ARG_PAGE, pageNumber); 
     fragment.setArguments(args); 
     return fragment; 
    } 

    public ScreenSlidePageFragment() { 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
    // Get max available VM memory, exceeding this amount will throw an 
     // OutOfMemory exception. Stored in kilobytes as LruCache takes an 
     // int in its constructor. 
     DisplayMetrics displaymetrics = new DisplayMetrics(); 
     getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); 
     height = displaymetrics.heightPixels; 
     width = displaymetrics.widthPixels; 
     final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 

     // Use 1/8th of the available memory for this memory cache. 
     final int cacheSize = maxMemory/8; 

     mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { 
      @Override 
      protected int sizeOf(String key, Bitmap bitmap) { 
       // The cache size will be measured in kilobytes rather than 
       // number of items. 
       return bitmap.getRowBytes()*bitmap.getHeight()/1024; 
      } 
     }; 

     mPageNumber = getArguments().getInt(ARG_PAGE); 
    } 

    public void addBitmapToMemoryCache(String key, Bitmap bitmap) { 
     if (getBitmapFromMemCache(key) == null) { 
      mMemoryCache.put(key, bitmap); 
     } 
    } 

    public Bitmap getBitmapFromMemCache(String key) { 
     return mMemoryCache.get(key); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) {  
    ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.image_view_layout, container, false); 
    img=(ImageView) rootView.findViewById(R.id.img_pager); 
    final String imageKey = String.valueOf(pics[count-mPageNumber]); 
    final Bitmap bitmap = getBitmapFromMemCache(imageKey); 
      if (bitmap != null) { 
        img.setImageBitmap(bitmap); 
       } else { 
        img.setImageResource(pics[count-mPageNumber]); 
        BitmapWorkerTask task = new BitmapWorkerTask(img); 
        task.execute(pics[count-mPageNumber]); 
       } 
     return rootView; 
    } 




    @Override 
    public void onDetach(){ 
     super.onDetach(); 
     super.onDetach(); 
     Bitmap bitmap = ((BitmapDrawable)img.getDrawable()).getBitmap(); 
     bitmap.recycle();  
     //FragmentManager fragmentManager = getFragmentManager(); 
     //FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
     //fragmentTransaction.remove(this).commit(); 
    } 


    /** 
    * Returns the page number represented by this fragment object. 
    */ 
    public int getPageNumber() { 
     return mPageNumber; 
    } 

    class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> { 
     private final WeakReference<ImageView> imageViewReference; 

     public BitmapWorkerTask(ImageView imageView) { 
      // Use a WeakReference to ensure the ImageView can be garbage collected 
      imageViewReference = new WeakReference<ImageView>(imageView); 
     } 

     // Decode image in background. 
     @Override 
     protected Bitmap doInBackground(Integer... params) { 
      final Bitmap bitmap = decodeSampledBitmapFromResource(getResources(), params[0],width,height); 
      addBitmapToMemoryCache(String.valueOf(params[0]), bitmap); 
      return bitmap; 
     } 

     // Once complete, see if ImageView is still around and set bitmap. 
     @Override 
     protected void onPostExecute(Bitmap bitmap) { 
      if (imageViewReference != null && bitmap != null) { 
       final ImageView imageView = imageViewReference.get(); 
       if (imageView != null) { 
        imageView.setImageBitmap(bitmap); 
       } 
      } 
     } 
    } 

    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
      int reqWidth, int reqHeight) { 

     // First decode with inJustDecodeBounds=true to check dimensions 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeResource(res, resId, options); 

     // Calculate inSampleSize 
     options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

     // Decode bitmap with inSampleSize set 
     options.inJustDecodeBounds = false; 
     return BitmapFactory.decodeResource(res, resId, options); 
    } 


    public static int calculateInSampleSize(
      BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 

     // Calculate ratios of height and width to requested height and width 
     final int heightRatio = Math.round((float) height/(float) reqHeight); 
     final int widthRatio = Math.round((float) width/(float) reqWidth); 

     // Choose the smallest ratio as inSampleSize value, this will guarantee 
     // a final image with both dimensions larger than or equal to the 
     // requested height and width. 
     inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 
    } 

    return inSampleSize; 
} 

} 

и активность:

import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentStatePagerAdapter; 
import android.support.v4.view.PagerAdapter; 
import android.support.v4.view.ViewPager; 
import android.view.Menu; 



public class Introduction_Activity extends FragmentActivity { 
    private static final int NUM_PAGES = 73; 

    private ViewPager mPager; 

    /** 
    * The pager adapter, which provides the pages to the view pager widget. 
    */ 
    private PagerAdapter mPagerAdapter; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_introduction); 


     // Instantiate a ViewPager and a PagerAdapter. 
     mPager = (ViewPager) findViewById(R.id.imgs_viewpager); 
     mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); 
     mPager.setAdapter(mPagerAdapter); 
     mPager.setCurrentItem(NUM_PAGES-1,false);  
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.introduction_, menu); 
     return true; 
    } 



    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { 
     public ScreenSlidePagerAdapter(FragmentManager fm) { 
      super(fm); 
     } 

     @Override 
     public Fragment getItem(int position) { 

      return ScreenSlidePageFragment.create(position); 

      } 

     @Override 
     public int getCount() { 
      return NUM_PAGES; 
     } 


    } 


} 

проблема:

10-02 06:21:48.230: E/dalvikvm-heap(8944): Out of memory on a 7071376-byte allocation. 
10-02 06:21:48.245: E/AndroidRuntime(8944): FATAL EXCEPTION: AsyncTask #4 
10-02 06:21:48.245: E/AndroidRuntime(8944): java.lang.RuntimeException: An error occured while executing doInBackground() 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at android.os.AsyncTask$3.done(AsyncTask.java:278) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at java.util.concurrent.FutureTask.setException(FutureTask.java:124) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at java.util.concurrent.FutureTask.run(FutureTask.java:137) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at java.lang.Thread.run(Thread.java:856) 
10-02 06:21:48.245: E/AndroidRuntime(8944): Caused by: java.lang.OutOfMemoryError 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at android.graphics.Bitmap.nativeCreate(Native Method) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at android.graphics.Bitmap.createBitmap(Bitmap.java:605) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at android.graphics.Bitmap.createBitmap(Bitmap.java:551) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:437) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:618) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:593) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:445) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:468) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at packagename.ScreenSlidePageFragment.decodeSampledBitmapFromResource(ScreenSlidePageFragment.java:178) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at packagename.ScreenSlidePageFragment$BitmapWorkerTask.doInBackground(ScreenSlidePageFragment.java:148) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at packagename.ScreenSlidePageFragment$BitmapWorkerTask.doInBackground(ScreenSlidePageFragment.java:1) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at android.os.AsyncTask$2.call(AsyncTask.java:264) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 
10-02 06:21:48.245: E/AndroidRuntime(8944):  ... 5 more 

ответ

8

Попробуйте

надстройку следующее в прикладной тег в манифесте

android:largeHeap="true" 

Надеюсь, это поможет вам.

+0

спасибо, что он отлично работал и работает ли он на телефонах со старыми версиями тоже? – User

+0

ya он отлично работает в моем приложении со старыми телефонами. @ User – Andrain

+5

Нельзя добавлять это, если вы не уверены, где ваша память будет использоваться, какие объекты, и вы обязательно должны их иметь. Это приведет к увеличению размера кучи, что может привести к тому, что GC будет чаще ударяться и, следовательно, увеличить время паузы. Проверьте этот диалог ввода-вывода в Google [Управление памятью Патриком Дуброем] (http://www.youtube.com/watch?v=_CruQY55HOk). –

0

aquire большой кучи, используя это в манифесте:

android:largeHeap="true" 

и почти все проблемные решения присутствуют на этих ссылках, связанных с памятью из ошибок:

meomry-out-of-error

Memory Leak and Out of memory Error using List,LinkedList and HashMap

Memory Leak and Out of memory Error using LRU Cache

Memory Leak and Out of memory Error using Disk LRU Cache

3
android:largeHeap="true" 

Это не является хорошим решением. Вы используете largeHeap, но этот тег добавлен с Android 3.0, а размер большой кучи вдвое больше первоначальной кучи. Это просто означает, что может быть так много чисел зависит от производителя устройства.

Вы должны найти решение, которое заботится об ошибке в памяти для всех типов устройств. Решение, подобное этому, будет работать на каком-то устройстве, но не на гарантии, что он будет работать везде. То, что я пытаюсь сказать, может закончиться большой кучей, которая по-прежнему меньше вашего требования.

LruCache неизвестно, что вы только что описали. по документации,

A cache that holds strong references to a limited number of values. Each time a value is accessed, it is moved to the head of a queue. When a value is added to a full cache, the value at the end of that queue is evicted and may become eligible for garbage collection. 

Удерживает сильную ссылку.

Так сделайте следующее,

  • оптимизации изображения. Отрегулируйте разрешение изображения на основе отображения устройства .если вам нужно отображать изображение с очень высоким разрешением, убедитесь, что в любой момент времени в памяти будет отображаться только видимое изображение.
  • Вместо сильной справки используйте ссылку на неделю и держите этот путь на памяти.
2

я столкнулся же проблемой и решить ее, как следует

Лучший пример приведен в руководстве для разработчиков андроида, следовать этот шаг за шагом руководство.

  1. реализации inJustDecodeBounds http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

  2. Следуйте инструкции ниже для асинхронных и кэширования, вы можете также загрузить образец из той же ссылке. http://developer.android.com/training/displaying-bitmaps/display-bitmap.html

0

Урок, который я узнал трудный путь, это, «Не изобретайте колесо». Используйте сторонние библиотеки, такие как Picasso, Fresco, Glide или тому подобное, чтобы выбраться из ситуации вроде этого. И еще одно замечание заключается в том, что вы код очень удобен.

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