0

I'm using a grid view which is inflating the custom_layout from the layout. The grid view is loading the videos from the phone and populating it in the form of thumbnails. Everything is working fine. There is a problem in scrolling of the grid view. It is scrolling slow and in phone whose API > 20 is giving the message

The app is not responding

I've followed this link but didn't found the perfect solution: Gridview is scrolling slow

I've used asynchronous task to load the videos from the gallery. I'm giving out the code for the same. Here is my fragment:

AddFragment.java:

public class AddFragment extends Fragment {

private ImageButton imageButton;
private GridView gridView;
private ProgressDialog videoProgressDialog;
ArrayList<File> list = new ArrayList<>();
ImageAdapter imageAdapter;

public AddFragment() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_add, container, false);

    imageButton = (ImageButton) view.findViewById(R.id.gotoButton);

    gridView = (GridView) view.findViewById(R.id.grid_view);
    gridView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    Log.e("ADD_VIDEOS","FRAGMENT CREATED");
    videoProgressDialog = new ProgressDialog(getContext());
    videoProgressDialog.setTitle("Loading Videos");
    videoProgressDialog.setMessage("please wait.....");
    videoProgressDialog.setCancelable(false);
    videoProgressDialog.show();

    LoadVideoTask videoTask = new LoadVideoTask();
    videoTask.execute(new File("/mnt"));

    return view;
}

//reading the file from the storage
void videoReader(File root) {


    File[] file = root.listFiles();

    if (file != null) {

        for (File aFile : file) {
            if (!aFile.isDirectory()) {
                if (aFile.getName().endsWith(".mp4")) {
                    Log.e("VIDEO_FILE=====", aFile.getName());
                    list.add(aFile);
                }
            } else
                videoReader(aFile);
        }
    } else{}
}

//Show hide select button if images are selected or deselected
public void showSelectButton() {
    ArrayList<String> selectedItems = imageAdapter.getCheckedItems();
    Log.e("CHECKED_ITEMS",imageAdapter.getCheckedItems().toString());
    if (selectedItems.size() > 0) {
        imageButton.setVisibility(View.VISIBLE);
    } else
        imageButton.setVisibility(View.GONE);

}

 class ImageAdapter extends BaseAdapter {


    private Bitmap bitmap;

    private LayoutInflater inflater;
     SparseBooleanArray mSparseBooleanArray;

    private final Context context;

    private ImageAdapter(Context c) {
        context = c;
        //changes done from here
        mSparseBooleanArray = new SparseBooleanArray();

    }

    //Method to return selected Images
    public ArrayList<String> getCheckedItems() {
        ArrayList<String> mTempArry = new ArrayList<String>();

        for (int i = 0; i < list.size(); i++) {
            if (mSparseBooleanArray.get(i)) {
                mTempArry.add(list.get(i).toString());
            }
        }

        return mTempArry;
    }


    //for the video numbers
    @Override
    public int getCount() {
        return list.size();
    }

    //for getting the video items position vise
    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }


    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {

        View v;

        if (convertView == null) {

            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(R.layout.custom_gridview,viewGroup,false);
            v.setLayoutParams(new AbsListView.LayoutParams(215,215));

        } else {
           // picturesView = (ImageView) convertView;
            v = (View)convertView;
        }

        Viewholder viewHolder = new Viewholder(v);
        //viewHolder.imageView.setId(position);
        viewHolder.id = position;
        //convertView.setTag(viewHolder);

        //loading images from the videos
        if (list.get(position).toString().contains(".jpg")) {
            bitmap = BitmapFactory.decodeFile(list.get(position).toString()); //Creation of Thumbnail of image
          //  viewHolder.imageView.setImageBitmap(bitmap);
        } else {
            if (list.get(position).toString().contains(".mp4")) {
                bitmap = ThumbnailUtils.createVideoThumbnail(list.get(position).toString(), 1); //Creation of Thumbnail of video
                viewHolder.imageView.setImageBitmap(bitmap);
            }
        }

        //picturesView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        //picturesView.setAdjustViewBounds(true);
        //picturesView.setLayoutParams(new GridView.LayoutParams(215, 215));
        //picturesView.setImageBitmap(bitmap);
        //setting layout params for every device

        viewHolder.checkBox.setTag(position);
        viewHolder.checkBox.setChecked(mSparseBooleanArray.get(position));
        CompoundButton.OnCheckedChangeListener mCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                mSparseBooleanArray.put((Integer) compoundButton.getTag(), isChecked);//Insert selected checkbox value inside boolean array
                showSelectButton();
            }
        };
        viewHolder.checkBox.setOnCheckedChangeListener(mCheckedChangeListener);


        //return picturesView;
        return v;

    }

     class Viewholder {
        public ImageView imageView;
        public CheckBox checkBox;
         public int id;
         public Viewholder(View v){
             imageView = (ImageView) v.findViewById(R.id.galleryImageView);
             checkBox = (CheckBox) v.findViewById(R.id.selectCheckBox);
         }
    }
}

//asynch task has been done to do the processing in the background for loading the videos
//three parametres are Params,Progress,Result
private class LoadVideoTask extends AsyncTask<File,Integer, Integer>{


    @Override
    protected Integer doInBackground(File... files) {
        for(int i=0;i<files.length;i++) {
            videoReader(files[i]);
            Log.e("VIDEO_LOAD", files[i].toString());
        }
        return files.length;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        videoProgressDialog.setProgress(values[0]);
    }

    @Override
    protected void onPostExecute(Integer integer) {
        super.onPostExecute(integer);
        updateUI();
    }
}

private void updateUI() {

    videoProgressDialog.dismiss();
    //calling imageadapter class in here
    imageAdapter = new ImageAdapter(getContext());
    //for not repeating of the files
    LinkedHashSet<File> fileList = new LinkedHashSet<>();
    fileList.addAll(list);
    list.clear();
    list.addAll(fileList);
    gridView.setAdapter(imageAdapter);

    imageButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(getContext(), EditVideoActivity.class);
            intent.putExtra("sendData", imageAdapter.getCheckedItems());   //passing the data
            Log.e("SEND_DATA", imageAdapter.getCheckedItems().toString());
            startActivity(intent);
        }
    });
}}

Since there is a lot of data and I know due to heavy data it is not scrolling slow. I need a solution for this.

After following this link I got a result and made some changes in the getView() according to the solution, which still does not solve my problem.

Link: GridView Smooth Scrolling Solution

My getView() method inside my Adapter class is like this now:

@Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {


        Viewholder viewHolder = null;

        if (convertView == null) {

            viewHolder = new Viewholder();

            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.custom_gridview,viewGroup,false);
            convertView.setLayoutParams(new AbsListView.LayoutParams(215,215));

            convertView.setTag(viewHolder);

        } else {
            viewHolder = (Viewholder) convertView.getTag();
        }

        viewHolder.imageView = (ImageView) convertView.findViewById(R.id.galleryImageView);
        viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.selectCheckBox);
        viewHolder.id = position;

        //loading images from the videos
        if (list.get(position).toString().contains(".jpg")) {
            bitmap = BitmapFactory.decodeFile(list.get(position).toString()); //Creation of Thumbnail of image
          //  viewHolder.imageView.setImageBitmap(bitmap);
        } else {
            if (list.get(position).toString().contains(".mp4")) {
                bitmap = ThumbnailUtils.createVideoThumbnail(list.get(position).toString(), 1); //Creation of Thumbnail of video
                viewHolder.imageView.setImageBitmap(bitmap);
            }
        }

        viewHolder.checkBox.setTag(position);
        viewHolder.checkBox.setChecked(mSparseBooleanArray.get(position));
        CompoundButton.OnCheckedChangeListener mCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                mSparseBooleanArray.put((Integer) compoundButton.getTag(), isChecked);//Insert selected checkbox value inside boolean array
                showSelectButton();
            }
        };
        viewHolder.checkBox.setOnCheckedChangeListener(mCheckedChangeListener);

        return convertView;

    }
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Alok
  • 8,452
  • 13
  • 55
  • 93
  • Check this link: https://developer.android.com/training/improving-layouts/smooth-scrolling.html . Or try to use RecycleView – Brian Hoang Aug 10 '17 at 14:04
  • The images are getting loaded.. the asynch task does that. But after loading the images it scrolls so slow – Alok Aug 10 '17 at 14:08
  • Is it the image manipulation that is causing the slowness? You are decoding a bitmap or creating a thumbnail from an .mp4 each time `getView()` is called. That has to take some time. Can that be done in advance on a background thread maybe part of the AsyncTask? – Cheticamp Aug 10 '17 at 14:18
  • No the actual problem is in the heavy data. The image are getting populated successfully, everything is working great. But when all the data comes up, now if want to scroll it is scrolling slow. And yes if the videos are less the problem is not there. **i'm sure you might be getting what I'm trying to say** – Alok Aug 10 '17 at 14:26

1 Answers1

0

Bitmaps can very easily exhaust an app's memory budget.

If your app is loading multiple bitmaps into memory, you need to skillfully manage memory and disk caching. So Whenever you load images from the videos, It must be exhaust an app's memory budget.

I recommend to use Picasso library.(http://square.github.io/picasso/)

Picasso.with(context).load(new File(YOUR_FILE_PATH)).into(imageView);

You have to change it in your source code.

if (list.get(position).toString().contains(".mp4")) {
            bitmap = ThumbnailUtils.createVideoThumbnail(list.get(position).toString(), 1); //Creation of Thumbnail of video
            Picasso.with(context).load(getImageUri(context, bitmap)).into(viewHolder.imageView);}

public Uri getImageUri(Context inContext, Bitmap inImage) {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
    String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
    return Uri.parse(path);
}

Also please read it

solving-the-android-image-loading-problem-volley-vs-picasso/

Handling Bitmaps

redAllocator
  • 725
  • 6
  • 12
  • i'll try and tell you the result – Alok Aug 10 '17 at 14:32
  • I've done this there were some changes though like, new File(list.get(position).toString()) and yes the **into is not being resolved as it is showing the Cannot resolve into(android.widget.imageView)** and one more thing where will be the bitmap thing used? – Alok Aug 10 '17 at 14:38
  • I've done what you've suggested me but this makes thing more complex, before this all images were getting populated at the same time but the scrolling was slow. Now the problem increases, when I scroll the images are getting shown on this time only and the scrolling is also too slow because of this. This is not the solution what I'm looking now. – Alok Aug 10 '17 at 14:58
  • please upload your full source such as github – redAllocator Aug 10 '17 at 15:13
  • I'm sorry but I can't, I'm not permitted to do so. This is the code in which I'm facing problem. You just have to look through the code – Alok Aug 11 '17 at 06:18