1

I am developing an Android application for tablet which will be used as a catalog of many products (around 10 000).

I display them in a gridview, I only display the 250 first, and if I reach the end of these 250 I load 250 more.

My problem is the pictures. My application seems to work when I scroll not quickly, it is smooth, and there is no problems but it can use 300 or 400 MB of RAM, so I guess I'm doing something badly. I heard that I'm supposed to use WeakReferences but I'm not sure how to use them... That was for the first "problem". (It is not really important since the user may only use this application, and if it works very well... But yes, if I can improve it I will try)

The other big problem here is that when I do something like :

  • Scroll fast to the bottom
  • Immediately scroll fast to the top

Some pictures of the "bottom" are displayed on the pictures of the "top" (and not temporarly, they change again only if I scroll and come back at them).

What I know actually :

  • The mechanism of the griview reuse the views. If I have 10 views visibles, When the 5 first are not visibles, they are used for the 5 next ones that will be visible. I don't know how many view are in this "recycler".
    • This means that when I scroll to the bottom I see the 5 views which were not visible in the place of the 5 next ones for a few moment then the good views are loaded. To not have this bad effect, I set a picture white (the color of my background) using the method setRecyclerListener().
  • I don't "recycle" / use the good way to load my pictures and recycle them but don't know how to make it better
  • I use animations, I don't think there is any link with my problem due to them
  • I load the pictures in AsyncTask, that seems to work, but the picures are always loaded (in fast scroll too) which is not really a good thing
  • When scrolling bottom then top quickly sometimes I have the wrong pictures displayed. It may happen in other cases.

    public class ProduitsAdapter extends ArrayAdapter<Article> {
        private final Activity context;
        private ArrayList<Article> params;
        private Resources res;
    
        static class ViewHolder {
            public TextView numero;
            public TextView design;
            public ImageView image;
            public ImageSwitcher imgSwitcher;
            public ImageView codeBarre;
            public TextView codeBarreText;
            public TextView colisage;
            public TextView col3;
            public TextView col4;
            public TextView col5;
            public String image_string = "";
            public boolean found = true;
            public ImageView nouveaute;
        }
    
        public ProduitsAdapter(Activity context, ArrayList<Article> params) {
            super(context, R.layout.list_single, params);
            res = Catalogue.activity.getResources();
            this.context = context;
            this.params = params;
        }
    
        public int getCount() {
            return params.size();
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View rowView = convertView;
            if (rowView == null) {
                LayoutInflater inflater = context.getLayoutInflater();
                ViewHolder viewHolder = new ViewHolder();
    
                if (Catalogue.type_aff.equals("list")) {
                    rowView = inflater.inflate(R.layout.list_single, null);
                    viewHolder.numero = (TextView) rowView
                            .findViewById(R.id.numero);
                    viewHolder.design = (TextView) rowView
                            .findViewById(R.id.designation);
                    viewHolder.col3 = (TextView) rowView.findViewById(R.id.col3);
                    viewHolder.col4 = (TextView) rowView.findViewById(R.id.col4);
                    viewHolder.col5 = (TextView) rowView.findViewById(R.id.col5);
                } else {
                    rowView = inflater.inflate(R.layout.fragment_grid_item, null);
                    viewHolder.numero = (TextView) rowView
                            .findViewById(R.id.numero);
                    viewHolder.design = (TextView) rowView
                            .findViewById(R.id.designation);
                    viewHolder.colisage = (TextView) rowView
                            .findViewById(R.id.grid_colisage);
                    viewHolder.codeBarre = (ImageView) rowView
                            .findViewById(R.id.code_barre);
                    viewHolder.codeBarreText = (TextView) rowView
                            .findViewById(R.id.code_barre_text);
                    viewHolder.nouveaute = (ImageView) rowView
                            .findViewById(R.id.img_nouveaute);
                }
                viewHolder.image = (ImageView) rowView.findViewById(R.id.img);
                rowView.setTag(viewHolder);
            }
    
            ViewHolder holder = (ViewHolder) rowView.getTag();
            if (Catalogue.type_aff.equals("list")) {
                holder.col3.setText(params.get(position).getColonne_pref(3));
                holder.col4.setText(params.get(position).getColonne_pref(4));
                holder.col5.setText(params.get(position).getColonne_pref(5));
            } else {
                if (params.get(position).isNouveaute()) {
                    holder.nouveaute.setImageResource(R.drawable.nouveaute);
                    holder.nouveaute.setVisibility(ImageView.VISIBLE);
                } else
                    holder.nouveaute.setVisibility(ImageView.GONE);
                holder.colisage.setText(params.get(position).getColisage());
                if (ProduitsFragment.barcodeVisible) {
                    holder.codeBarreText.setText(params.get(position)
                            .getGencodNegoce());
                }
            }
            holder.numero.setText(params.get(position).getCodeArt());
            holder.design.setText(params.get(position).getDesignation_pref());
    
            // This is how I store my pictures, because finding one picture in a folder of 10 000 pictures takes too much time
            String pattern_deb = holder.numero.getText() + "";
            String chemin = Environment.getExternalStorageDirectory().getPath()
                    + res.getString(R.string.chemin_app_data)
                    + MainActivity.listDossiersSocietes
                            .get(MainActivity.societeSelected)
                    + res.getString(R.string.chemin_dossier_photos);
            for (int i = 0; i < pattern_deb.length() - 2; i++) {
                chemin += "/" + pattern_deb.charAt(i);
            }
            chemin += "/";
            File f = new File(chemin + params.get(position).getFichierPhoto());
            if (f.exists()) {
                holder.image_string = f.getAbsolutePath();
                new loadImagesFromFileThread(holder, position).execute();
                if (!Catalogue.type_aff.equals("list")
                        && ProduitsFragment.barcodeVisible)
                    new loadBarCodeThread(holder, position).execute();
            } else {
                holder.image.setImageResource(R.drawable.notfound300);
            }
            return rowView;
        }   
    
        private BitmapDrawable loadImagesFromFile(ViewHolder holder, int position) {
            holder.found = true;
            File bmp = new File(holder.image_string);
            if (bmp.exists() && !bmp.isDirectory()) {
                if (position < ProduitsFragment.gridView.getFirstVisiblePosition()
                        && position > ProduitsFragment.gridView
                                .getLastVisiblePosition()) {
                    holder.found = false;
                    return null;
                } else {
                    if (holder.image.getVisibility() == ImageView.VISIBLE) {
                        holder.found = false;
                        return null;
                    }
                }
    
                Bitmap myBitmap = BitmapFactory.decodeFile(bmp.getAbsolutePath());
                int width = myBitmap.getWidth();
                int height = myBitmap.getHeight();
                int newWidth = 200;
                int newHeight = 200;
                if (Catalogue.type_aff.equals("list")) {
                    newWidth = 40;
                    newHeight = 40;
                } else {
                    if (Catalogue.nbGrid == 5) {
                        newWidth = 200;
                        newHeight = 200;
                    }
                    if (Catalogue.nbGrid == 3) {
                        newWidth = 300;
                        newHeight = 300;
                    }
                }
                float scaleWidth = ((float) newWidth) / width;
                float scaleHeight = ((float) newHeight) / height;
                Matrix matrix = new Matrix();
                matrix.postScale(scaleWidth, scaleHeight);
                Bitmap resizedBitmap = Bitmap.createBitmap(myBitmap, 0, 0, width,
                        height, matrix, true);
                BitmapDrawable bmd = new BitmapDrawable(context.getResources(),
                        resizedBitmap);
                return bmd;
            } else {
                holder.found = false;
                return null;
            }
        }
    
        private class loadImagesFromFileThread extends
                AsyncTask<Void, Void, BitmapDrawable> {
            ViewHolder holder;
            int position;
            public loadImagesFromFileThread(ViewHolder holder, int position) {
                this.holder = holder;
                this.position = position;
                this.holder.image.setVisibility(ImageView.INVISIBLE);
            }
    
            @Override
            protected BitmapDrawable doInBackground(Void... params) {
                return loadImagesFromFile(holder, position);
            }
    
            @Override
            protected void onPostExecute(BitmapDrawable bmd) {
                if (ProduitsFragment.isNotScrolling) {
                    if (bmd != null) {
                        holder.image.setImageDrawable(bmd);
                        if (holder.image.getVisibility() != ImageView.VISIBLE
                                && !(position < ProduitsFragment.gridView
                                        .getFirstVisiblePosition() && position > ProduitsFragment.gridView
                                        .getLastVisiblePosition())) {
                            Animation fadeIn = new AlphaAnimation(0, 1);
                            fadeIn.setInterpolator(new DecelerateInterpolator());
                            fadeIn.setDuration(500);
                            fadeIn.setStartOffset(500);
                            holder.image.startAnimation(fadeIn);
                            holder.image.setVisibility(ImageView.VISIBLE);
                        }
                    } else {
                        if (position < ProduitsFragment.gridView
                                .getFirstVisiblePosition()
                                && position > ProduitsFragment.gridView
                                        .getLastVisiblePosition()) {
                            Log.e("DEBUG", "...");
                        } else {
                            if (holder.image.getVisibility() != ImageView.VISIBLE) {
                                if (!holder.found) {
                                    if (Catalogue.type_aff.equals("list")) {
                                        holder.image
                                                .setImageResource(R.drawable.notfound40);
                                    } else {
                                        if (Catalogue.nbGrid == 5) {
                                            holder.image
                                                    .setImageResource(R.drawable.notfound200);
                                        }
                                        if (Catalogue.nbGrid == 3) {
                                            holder.image
                                                    .setImageResource(R.drawable.notfound300);
                                        }
                                    }
                                    Animation fadeIn = new AlphaAnimation(0, 1);
                                    fadeIn.setInterpolator(new DecelerateInterpolator());
                                    fadeIn.setDuration(500);
                                    holder.image.startAnimation(fadeIn);
                                    holder.image.setVisibility(ImageView.VISIBLE);
                                } else {
                                    Animation fadeIn = new AlphaAnimation(0, 1);
                                    fadeIn.setInterpolator(new DecelerateInterpolator());
                                    fadeIn.setDuration(500);
                                    holder.image.startAnimation(fadeIn);
                                }
                                holder.image.setVisibility(ImageView.VISIBLE);
    
                            }
                        }
                    }
                }
            }
        }
    }
    

I would appreciate any help to correct the problem of the wrong pictures, and if anyone can explain me how to load them properly with some code if possible (without using 300 MB of RAM) that would be really nice.

leb1755
  • 1,386
  • 2
  • 14
  • 29
  • 1
    try with Universal Image Loader, It is very good library to deal with the images.https://github.com/nostra13/Android-Universal-Image-Loader – Chaitu Jul 31 '14 at 10:33
  • I agree, you should consider using any library for loading your images, UIL, Picasso or something – elmorabea Jul 31 '14 at 10:54
  • I used them, but it still seem to use a lot of memory (I used UIL and Picasso), but I don't have bugs with them (using UIL makes my gridview smoother also). I guess I'll stay with this until I get more time to work on it. – leb1755 Aug 01 '14 at 07:11

0 Answers0