Gridview Adapter can't read from external storage, werid loop iterations

I have had a basic Gridview sample from Google's documentation, which worked perfectly.

I also have some code that provides result as ArrayList with Bitmaps of last created pictures in Android's external storage (Permissions in manifest are granted) and that code also worked just fine on other project.

When I merged that concepts into one simple app code isn't working at all, activity remains empty till app crashes. However I noticed something interesting: There's a for loop which has defined number of iterations by int capacity but in Logcat I can see that number of iterations in this loop surpassing declared int value, basically that's reason why app crashes (outOfBoundsException).

So i Have those 2 problems and sitting on that for couple of hours... here is my code:

MainActivity.java

    package com.example.patryk.hellogridview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        GridView gridview = findViewById(R.id.gridview);
        gridview.setAdapter(new ImageAdapter(this));

        gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View v,
                                    int position, long id) {
                Toast.makeText(MainActivity.this, "" + position,
                        Toast.LENGTH_SHORT).show();
            }
        });
    }

PhotosReader.java

    package com.example.patryk.hellogridview;

import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.provider.MediaStore;
import android.util.Log;

import java.util.ArrayList;

public class PhotosReader {

    private int capacity = 5;
    private ArrayList<Bitmap> photos = new ArrayList<Bitmap>(capacity);

    public int getCapacity() {
        return capacity;
    }
    public void setCapacity(int capacity) {
        this.capacity = capacity;
    }
    public void setPhotos(ArrayList<Bitmap> photos) {
        this.photos = photos;
    }

    public PhotosReader() {
    }

    public ArrayList<Bitmap> getPhotos(Context context) {
        String[] projection = new String[]{
                MediaStore.Images.ImageColumns._ID,
                MediaStore.Images.ImageColumns.DATA,
                MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
                MediaStore.Images.ImageColumns.DATE_TAKEN,
                MediaStore.Images.ImageColumns.MIME_TYPE
        };
        Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null,
                null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");

        cursor.moveToFirst();
        for(int i = 1; i<=capacity; i++){
            photos.add(BitmapFactory.decodeFile(cursor.getString(1)));
            cursor.moveToNext();
            Log.d("photos.add", "iteration");
        }
        return photos;
    }

    public Bitmap getPhotosBitmap(ArrayList photos, int position){
        Bitmap bm = (Bitmap) photos.get(position);
        return bm;
    }



}

ImageAdapter.java

    package com.example.patryk.hellogridview;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;

public class ImageAdapter extends BaseAdapter {
    private Context mContext;

    public ImageAdapter(Context c) {
        mContext = c;
    }

    public int getCount() {
        return 0;
    }

    public Object getItem(int position) {
        return null;
    }

    public long getItemId(int position) {
        return 0;
    }

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {
            // if it's not recycled, initialize some attributes
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8, 8, 8, 8);
        } else {
            imageView = (ImageView) convertView;
        }

        PhotosReader PR = new PhotosReader();
        imageView.setImageBitmap(PR.getPhotosBitmap(PR.getPhotos(mContext), position));
        return imageView;
    }

}

1 answer

  • answered 2018-01-13 17:32 Napster

    This function inside ImageAdapter should not return 0. It should return the number of images that you want to show in the grid so should return capacity in your case. GridView assumes that there are 0 things to show

    public int getCount() {
            return 0;
    }
    

    change this to

    public int getCount() {
            return capacity;
    }
    

    Actually the correct way to do this would be to pass the PhotoReader object from the ImageAdapter constructor using ImageAdapter(context,photoReader) and then use photoReader.getCapacity() in getCount() function