从“文件”将图像加载到View Pager时出现内存不足错误

时间:2016-03-26 20:30:07

标签: android android-fragments android-viewpager out-of-memory android-drawable

我有一个使用cn.trinea.android.view.autoscrollviewpager的Viewpager:android-auto-scroll-view-pager:1.1.2库。我一直收到OOM错误(见底部)。我正在使用上面的库调用ViewPager,该库位于我正在使用TabManager的View Pager中的片段(见下文)。

编辑我已尝试过以下任务:

  1. 添加回收位图的步骤(根据以下建议删除)
  2. 在mainfest
  3. 中更改为大堆大小
  4. 添加了建议的位图图片
  5. 添加了缓存
  6. 根据android建议添加了位图工作人员任务
  7. 添加了Async Drawble
  8. 适配器位于以下位置:已修改

    public class HomeGalleryAdapter extends PagerAdapter implements OnPageChangeListener {
    
    
    
    RequestQueue requestQueue;
    int currentPage;
    private LruCache<String, Bitmap> mMemoryCache;
    
    
    static ArrayList<Integer> intentInfo = new ArrayList<>();
    static ArrayList<String> quizImage = new ArrayList<>();
    static ArrayList<String> downloads = new ArrayList<>();
    CognitoCachingCredentialsProvider cp;
    final Context c;
    SharedPreferences sp;
    String density;
    
    public HomeGalleryAdapter(Context context){
        c =context;
        cp = AmazonS3.getProvider(c);
        intentInfo.clear();
        quizImage.clear();
        sp = PreferenceManager.getDefaultSharedPreferences(c);
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        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.getByteCount() / 1024;
            }
        };
    
        String cognitioID = sp.getString("Cognito","");
        density = sp.getString("screenDensity", "");
    
    
        String requestURL = "http://XXXXXX/top_5_sponsers.php?format=json&device_id="+cognitioID;
    
    
        requestQueue = Volley.newRequestQueue(context);
        JsonObjectRequest jor = new JsonObjectRequest(Request.Method.GET, requestURL, null,
        new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                    Log.i("Home Gallery Adapter ", "Volley");
                try{
    
                    JSONArray ja = response.getJSONArray("posts");
    
    
    
                    for(int i=0; i < ja.length(); i++){
    
                        JSONObject jsonObject = ja.getJSONObject(i);
    
                        JSONObject interior = jsonObject.getJSONObject("post");
    
                        intentInfo.add(i, interior.getInt("iquizontap_quiz_ID"));
    
                        quizImage.add(i, interior.getString("QUIZ_SPONSER_IMAGE"));
    
                        int a = c.getResources().getIdentifier(interior.getString
                                ("QUIZ_SPONSER_IMAGE"),"drawable",c.getPackageName());
    
                        if(a == 0){
                            downloads.add(interior.getString
                                    ("QUIZ_SPONSER_IMAGE"));
                            Log.i("added a file", interior.getString("QUIZ_SPONSER_IMAGE"));
                        }
                    }
                     new imageDownloads().execute();
    
                }catch(JSONException e){
                    e.printStackTrace();
                }
            }
        },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.e("Volley","Error "+error);
    
                    }
                }
        );
    
        requestQueue.add(jor);
    
        notifyDataSetChanged();
    
    
    }
    
    
    
    @Override
    public int getCount() {
    
        notifyDataSetChanged();
        return quizImage.size();
    
    
    }
    
    @Override
    public boolean isViewFromObject(View view, Object object) {
    
        return view == (object);
    }
    
    
    
    
    @Override
    public Object instantiateItem(ViewGroup container, int position){
    
    
        Log.i("Home Gallery Adapter", "instantiateItem");
    
        final int innerposition = position;
        final ImageButton imageButton = new ImageButton(c);
        int imageHeight = imageButton.getHeight();
        int imageWidth = imageButton.getWidth();
        String bitmapFileName = c.getCacheDir() + File.separator + quizImage.get(position).trim() + ".png";
        imageDownloadParams params = new imageDownloadParams(bitmapFileName, imageWidth, imageHeight);
    
    
    
        if(cancelPotentialWork(bitmapFileName, imageButton)) {
    
           final Bitmap bitmap = getBitmapFromMemCache(bitmapFileName);
    
            if(bitmap != null) {
    
                BitmapWorkerTask task = new BitmapWorkerTask(imageButton);
                final AsyncDrawable asyncDrawable =
                        new AsyncDrawable(c.getResources(), BitmapFactory.decodeResource(c.getResources(), R.drawable.quizontap_default), task);
    
    
                imageButton.setBackground(asyncDrawable);
                task.execute(params);
            }
    
        }
    
        Log.i("Home Gallery Adapter", "Insitate Item after set Image");
    
    
        (container).addView(imageButton, 0);
    
    
    
        imageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public  void onClick(View v) {
                Intent quizIntent = new Intent(c,QuestionActivity.class);
                quizIntent.putExtra("company", getItem(innerposition));
                quizIntent.putExtra("tab",1);
                c.startActivity(quizIntent);
                Log.i("intent from onClick", quizIntent.getIntExtra("company" , 1)+"");
            }
        });
    
    
        return imageButton;
    
    
    
    }
    
    public Integer getItem(int index){
       return intentInfo.get(index);
    }
    
    
    
    @Override
    public void destroyItem(ViewGroup container, int position, Object object){
        ((ViewPager) container).removeView((ImageButton) object);
    
        final int innerposition = position;
        final ImageButton imageButton = new ImageButton(c);
    
        Drawable drawable = imageButton.getDrawable();
        if (drawable instanceof BitmapDrawable){
            BitmapDrawable bd = (BitmapDrawable) drawable;
            Bitmap bitmap = bd.getBitmap();
    
            bitmap.recycle();
        }
    }
    
    
     @Override
     public void onPageSelected(int newPageIndex) {
            currentPage = newPageIndex;
     }
    
    @Override
    public void onPageScrollStateChanged(int newPageIndex) {
    
    }
    
    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
    
    
    
    }
    
    @Override
    public float getPageWidth(int position){
        return 0.93f;
    }
    
    
    
    public class imageDownloads extends AsyncTask<String, Void, String> {
    
    
    
        @Override
        protected String doInBackground(String... params) {
            Log.i("Home Gallery", "In home Gallery Image Download");
            for(int i = 0 ; i<downloads.size(); i++){
    
                Log.i("file name to dl",downloads.get(i));
    
                String fileName = c.getCacheDir()+ File.separator+downloads.get(i).trim()+".png";
    
                File d = new File(fileName);
    
    
                if(!d.exists() || d.length() == 0) {
                    AmazonS3.createFile(downloads.get(i), c);
    
                }
    
                TransferUtility transferUtility = new TransferUtility(qotSingleton.getInstance(c).getAmazonS3Client(), c);
    
                TransferObserver observer = transferUtility.download("quizontapimages/quizimages", downloads.get(i).trim()+ density+ ".png", d);
    
    
                observer.setTransferListener(new TransferListener() {
                    @Override
                    public void onStateChanged(int fileName, TransferState transferState) {
    
                    }
    
                    @Override
                    public void onProgressChanged(int fileName, long l, long l1) {
                        int percentage = (int) (l/l1);
    
                    }
    
                    @Override
                    public void onError(int fileName, Exception e) {
                        Log.i("home gallery", e +"");
    
                    }
                });
    
            }return "test";
        }
    
    
        protected void onPreExecute(String test) {
    
        }
    
        // onPostExecute displays the results of the AsyncTask.
    
    
    
    
        protected void onPostExecute(String test) {
    
    
    
    
    
    
            notifyDataSetChanged();
    
    
    }
    }
    
    
    class BitmapWorkerTask extends AsyncTask<imageDownloadParams, Void, Bitmap>{
        private final WeakReference<ImageButton> imageButtonWeakReference;
        private String filename = "";
        private int height;
        private int width;
    
        public BitmapWorkerTask(ImageButton imageButton){
            imageButtonWeakReference = new WeakReference<ImageButton>(imageButton);
        }
    
        @Override
        protected Bitmap doInBackground(imageDownloadParams ... params){
            filename = params[0].fileName;
            height = params[0].height;
            width = params[0].width;
    
            final Bitmap bitmap =decodeSampledBitmap(filename, width, height);
    
            addBitmapToMemoryCache(params[0].fileName, bitmap);
    
    
            return bitmap;
    
        }
    
        @Override
        protected  void onPostExecute(Bitmap bitmap){
            if (imageButtonWeakReference != null && bitmap !=null){
                final ImageButton imageButton = imageButtonWeakReference.get();
                final BitmapWorkerTask bitmapWorkerTask = getBitmapWOrkerTask(imageButton);
    
                if(this== bitmapWorkerTask && imageButton != null){
                    imageButton.setImageBitmap(bitmap);
                }
    
            }
    
    
        }
    
    
    
    
    
    }
    
    
    public static Bitmap decodeSampledBitmap(String f, int reqWidth, int reqHeight) {
    
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(f,  options);
    
        // Calculate inSampleSize
        options.inSampleSize = CommonUtilities.calculateInSampleSize(options, reqWidth, reqHeight);
    
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(f, options);
    }
    
    
    public static class imageDownloadParams {
        String fileName;
        int width;
        int height;
    
        imageDownloadParams(String fileName, int width, int height){
            this.fileName = fileName;
            this.width = width;
            this.height = height;
        }
    }
    
    static class AsyncDrawable extends BitmapDrawable{
        private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskWeakReference;
    
        public AsyncDrawable(Resources res , Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask){
            super(res, bitmap);
            bitmapWorkerTaskWeakReference = new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
        }
    
        public BitmapWorkerTask getBitMapWorkerTask(){
            return bitmapWorkerTaskWeakReference.get();
        }
    }
    
    
    public static boolean cancelPotentialWork(String filename, ImageButton imageButton){
        final BitmapWorkerTask bitmapWorkerTask = getBitmapWOrkerTask(imageButton);
    
        if (bitmapWorkerTask != null){
            final String bitmapData = bitmapWorkerTask.filename;
    
            if(bitmapData == "" || bitmapData != filename){
                bitmapWorkerTask.cancel(true);
            } else {
                return false;
            }
    
        }
    
        return true;
    }
    
    private static BitmapWorkerTask getBitmapWOrkerTask(ImageButton imageButton){
        if(imageButton != null){
            final Drawable drawable = imageButton.getDrawable();
            if(drawable instanceof AsyncDrawable){
                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
                return asyncDrawable.getBitMapWorkerTask();
            }
        }
    
        return null;
    }
    
    public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
        if (getBitmapFromMemCache(key) == null) {
            mMemoryCache.put(key, bitmap);
        }
    }
    
    public Bitmap getBitmapFromMemCache(String key) {
        return mMemoryCache.get(key);
    }
    

    }

    我是从这里打电话的:

    public class MainFragment extends Fragment {
    ImageButton playquiz;
    ImageButton watchvideo;
    AutoScrollViewPager galleryPager;
    
    
    static ArrayList <String> videos= new ArrayList<>();
    static ArrayList<Integer> quizNo = new ArrayList<>();
    
    boolean running;
    HomeGalleryAdapter adapter;
    View rootView;
    RequestQueue requestQueue;
    String cognitioID;
    Context context;
    Integer downloadFlag;
    
    
    
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        rootView = inflater.inflate(R.layout.fragment_mainfragment, container, false);
        downloadFlag = 0;
    
        SharedPreferences accountInfo = PreferenceManager.getDefaultSharedPreferences(getActivity());
        cognitioID = accountInfo.getString("Cognito", "");
    
        context = getActivity();
        Log.i("context in MF", context + "");
        running = true;
        galleryPager = (AutoScrollViewPager) rootView.findViewById (R.id.homegallery);
        playquiz = (ImageButton) rootView.findViewById(R.id.playquiz);
        watchvideo = (ImageButton) rootView.findViewById(R.id.watchvideo);
    
    
    
    
    
        if(quizNo.isEmpty()) {
               QuizLoad();
                }
    
        adapter = new HomeGalleryAdapter(getActivity());
        adapter.notifyDataSetChanged();
    
        galleryPager.setAdapter(adapter);
        galleryPager.setClipToPadding(false);
        galleryPager.setPageMargin(10);
        galleryPager.setInterval(4000);
        galleryPager.startAutoScroll(4000);
    
    
    
    
    
        playquiz.setOnClickListener(new OnClickListener() {
    
            @Override
            public void onClick(View v) {
                Intent quizoutIntent = new Intent(getActivity(), QuestionActivity.class);
                quizoutIntent.putExtra("company", getCompanyName(galleryPager.getCurrentItem()));
                quizoutIntent.putExtra("tab", 0);
    
                startActivity(quizoutIntent);
    
            }
    
    
        });
    
        watchvideo.setOnClickListener(new OnClickListener(){
    
            @Override
            public void onClick(View v){
                startActivity(new Intent(Intent.ACTION_VIEW,
                        Uri.parse(videos.get(galleryPager.getCurrentItem()))));
    
            }
    
    
        });
    
    
       galleryPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if (videos.get(position).isEmpty()){
                    watchvideo.setVisibility(View.INVISIBLE);
                } else
                    watchvideo.setVisibility(View.VISIBLE);
    
    
            }
    
            @Override
            public void onPageSelected(int position) {
    
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
    
            }
        });
    
        return rootView;
    }
    
    public Integer getCompanyName(int index){
    
        return quizNo.get(index);
    }
    
    public MainFragment() {
        // TODO Auto-generated constructor stub
    }
    
    
    
    
    
    @Override
    public void onPause(){
        super.onPause();
        running = false;
        galleryPager.stopAutoScroll();
    }
    
    @Override
    public void onStop(){
        super.onStop();
        running = false;
        galleryPager.stopAutoScroll();
    
    }
    
    @Override
    public void onResume(){
        super.onResume();
        running = true;
        if(quizNo.isEmpty()) {
    
    
            QuizLoad();
    
    
        }
       adapter.notifyDataSetChanged();
       galleryPager.startAutoScroll(4000);
    
    
    }
    
    
    public void QuizLoad(){
        Log.i("MainFragment", "quizNo is Empty");
    
    
        String requestURL = "XXX.php?format=json&device_id="+cognitioID;
    
    
        requestQueue = Volley.newRequestQueue(context);
        JsonObjectRequest jor = new JsonObjectRequest(Request.Method.GET, requestURL, null,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
    
                        try{
    
                            JSONArray ja = response.getJSONArray("posts");
    
    
    
                            for(int i=0; i < ja.length(); i++){
    
                                JSONObject jsonObject = ja.getJSONObject(i);
    
    
                                JSONObject interior = jsonObject.getJSONObject("post");
    
                                quizNo.add(i, interior.getInt("iquizontap_quiz_ID"));
    
                                videos.add(i, interior.getString("VIDEO_URL"));
                            }
    
    
    
                        }catch(JSONException e){
                            e.printStackTrace();
                        }
    
    
    
    
    
    
    
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.e("Volley","Error "+error);
    
                    }
                }
        );
    
        requestQueue.add(jor);
    
    
    }
    

    }

    没有任何改变,但可能是图像的大小(整体上的图像实际上已经缩小了)。在加载此片段之前,我将上一个活动中的五个图像加载到Cache目录中,然后检查它们是否在那里,如果没有下载它们。

    我尝试增加堆大小,回收映像(请参阅适配器中的destroyItem。相反,当我尝试初始化适配器时,我收到以下错误: ADDED

    D/Error: ERR: stack=java.lang.StackOverflowError: stack size 8MB at     android.support.v4.view.ViewPager.b(SourceFile:956)
    ....
    E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 13408152)
    03-28 23:53:34.144 745-745/com.brillada.quizontap E/AndroidRuntime: Error reporting crash
                                                                    android.os.TransactionTooLargeException: data parcel size 13408152 bytes
                                                                        at android.os.BinderProxy.transactNative(Native Method)
                                                                        at android.os.BinderProxy.transact(Binder.java:503)
                                                                        at android.app.ActivityManagerProxy.handleApplicationCrash(ActivityManagerNative.java:4425)
                                                                        at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:90)
                                                                        at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
                                                                        at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
    

1 个答案:

答案 0 :(得分:0)

以下链接提供了有关如何有效解码图像的一些提示。它解释了为什么,即使图像不是现在的标准太大(我们应该有Gbs的内存,而你有13 Mb的问题),你有系统架构所施加的限制。其中一篇文章告诉您如何对图像进行缩减采样:

http://developer.android.com/training/displaying-bitmaps/index.html

我同意Doug Stevenson的观点。我建议在将它们带入内存时使用下采样。<​​/ p>

摘自文章:

  

告诉解码器对图像进行二次采样,将较小的版本加载到内存中,在BitmapFactory.Options对象中将inSampleSize设置为true。例如,使用inSampleSize为4解码的分辨率为2048x1536的图像会产生大约512x384的位图。将其加载到内存中对于完整图像使用0.75MB而不是12MB(假设ARGB_8888的位图配置)。这是一种根据目标宽度和高度计算样本大小值为2的幂的方法: