0

This custom listview is kicking my butt. I have been searching for a solution to this problem, but I can't find anyone else who has set up images and databases in the same way as I.

I have a SQLite driven app that takes a picture and saves the picture in External Storage folder called /Pictures and only saves the file name in the database as a String (i.e. 20190815_062534.jpg).

I want a custom listview that uses the file name from the database to call the image from the /Pictures folder.

I have previously created a different Activity that shows individual records and I used the method below to retrieve the image for that activity...

private void getImage(String infotopassFile) {
        String photoPath = Environment.getExternalStorageDirectory() + "/Pictures/" + infotopassFile;
        File file = new File(photoPath);
        if(file.canRead()) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
            Bitmap bitmap = BitmapFactory.decodeFile(photoPath, options);
            ImageView ivPicture_view = (ImageView) findViewById(R.id.ivPicture_view);
            ivPicture_view.setImageBitmap(bitmap);
        }
        else {
            Toast.makeText(ViewRecordActivity.this, "IMAGE FILE COULD NOT BE FOUND", Toast.LENGTH_LONG).show();

        }
    }

Also, I used a variation of the code above in a PDFwriter to display the image in a report. Both of those operations are working just fine, so I know all of the images exist and all are accessible, and I know my method of calling the images is workable.

The problem is, I can't figure out when and where to call the function getImage() (or some variation of it) to get the app to call the images at the right time. Every place I try to put it causes the app to crash when I try to call the Activity that has the custom listview.

I realize the solution is going to be more complicated than just randomly sticking a couple of lines of code in a single location, but I need some help finding a starting point.

I have the Activity that requests information from the database as an array. I have a SQLiteHelper that runs the query and returns the array. I have a custom list adapter that sets the array to the individual parts of the listview. And I have a class to handle the individual records and I honestly don't really understand what it does, but it works.

In which of those files would I start trying to retrieve the image?

The code below are the four java files that I referenced above. They are currently pulling the text from the database and displaying it in a listview, and it works without issue. I just can't figure out where I need to start making references to the picture in the external location.

//**********SQLLiteHelper.java**********

public class SQLLiteHelper extends SQLiteOpenHelper {

    //This is the query for the custom list adapter
    public ArrayList<Records> getAllRecords(){
        SQLiteDatabase db = this.getWritableDatabase();
        ArrayList<Records> myList = new ArrayList<Records>();
        String query = "SELECT fld_ID, fldName , fldFile FROM TABLE_table ORDER BY fld_ID DESC";
        Cursor cursor = db.rawQuery(query, null);

        while (cursor.moveToNext())
        {
            String ID = cursor.getString(cursor.getColumnIndex("fld_ID"));
            String NAME = cursor.getString(cursor.getColumnIndex("fldName"));
            String FILE = cursor.getString(cursor.getColumnIndex("fldFile"));
            String PATH = Environment.getExternalStorageDirectory() + "/Pictures/" + FILE;

            myList.add(new Records(ID, NAME, FILE, PATH));
        }

        return myList;

    }
}


//********** ActivityCustomListView.java**********

public class ActivityCustomListView extends AppCompatActivity {

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

        //identify the custom list view container in activity layout file
        ListView mListView = (ListView)findViewById(R.id.customListViewContainer);

        //get array of data from database
        SQLLiteHelper db = new SQLLiteHelper(this);
        ArrayList<Records> recordsArray = db.getAllRecords();

        //call the custom adapter
        CustomListAdapter adapter = new CustomListAdapter(this, R.layout.custom_record,recordsArray);

        //set the listview to the adapter
        mListView.setAdapter(adapter);
    }
}


//********** CustomListAdapter.java**********

public class CustomListAdapter extends ArrayAdapter<Records> {
    private Context mContext;
    private int mResource;
    private int lastPosition = -1;

    private static class ViewHolder{
        TextView ID;
        TextView Name;
        TextView File;
        TextView Path;
    }

    public CustomListAdapter(Context context, int resource, ArrayList<Records>objects){
        super (context, resource, objects);
        mContext = context;
        mResource = resource;
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        String ID = getItem(position).getID();
        String NAME = getItem(position).getName();
        String FILE = getItem(position).getFile();
        String PATH = getItem(position).getPath();

        Records records = new Records(ID,NAME,FILE,PATH);

        final View result;
        ViewHolder holder;

        if(convertView == null){
            LayoutInflater inflater = LayoutInflater.from(mContext);
            convertView = inflater.inflate(mResource, parent, false);
            holder = new ViewHolder();
            holder.ID = (TextView)convertView.findViewById(R.id.tvcID);
            holder.Name = (TextView)convertView.findViewById(R.id.tvcName);
            holder.File = (TextView)convertView.findViewById(R.id.tvcFile);
            holder.Path = (TextView)convertView.findViewById(R.id.tvcPath);

            result = convertView;

            convertView.setTag(holder);
        }
        else{
            holder=(ViewHolder)convertView.getTag();
            result = convertView;
        }

        holder.ID.setText(records.getID());
        holder.Name.setText(records.getName());
        holder.File.setText(records.getFile());
        holder.Path.setText(records.getPath());

        return convertView;
    }
}

    //********** Records.java**********

public class Records {

    private String ID;
    private String NAME;
    private String FILE;
    private String PATH;

    public Records(String id, String name, String file, String path) {
        this.ID = id;
        this.NAME = name;
        this.FILE = file;
        this.PATH = path;
    }

    public String getID(){
        return ID;}

    public String getName(){
         return NAME;}

    public String getFile(){
          return FILE;}

    public String getPath(){
           return PATH;}

}
Matthew
  • 139
  • 1
  • 10

1 Answers1

0

I figured it out!!!! Yay me!!!

I'm posting the updated code because someone else may be looking for a similar solution. The way I got my custom list to work with a picture saved in external memory is by going all the way back to the original SQLite query and having the array that was created add a new Bitmap element. Then carrying that element through the other operations. It may not be the right way to do it, but it works.

//**********SQLLiteHelper.java**********

public class SQLLiteHelper extends SQLiteOpenHelper {

//This is for the custom list adapter
    public ArrayList<Records> getAllRecords(){
        SQLiteDatabase db = this.getWritableDatabase();
        ArrayList<Records> myList = new ArrayList<Records>();
        String query = "SELECT fld_ID, fldName , fldFile FROM TABLE_table ORDER BY fld_ID DESC";
        Cursor cursor = db.rawQuery(query, null);

        while (cursor.moveToNext())
        {
            String ID = cursor.getString(cursor.getColumnIndex("fld_ID"));
            String NAME = cursor.getString(cursor.getColumnIndex("fldName"));
            String FILE = cursor.getString(cursor.getColumnIndex("fldFile"));
            String PATH = Environment.getExternalStorageDirectory() + "/Pictures/" + FILE;

                File photoFILEasFILE = new File(PATH);
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                Bitmap photoAsBitmap = BitmapFactory.decodeFile(String.valueOf(photoFILEasFILE), options);

            myList.add(new Records(ID, NAME, FILE, PATH, photoAsBitmap));
        }

        return myList;

    }



//********** ActivityCustomListView.java**********

public class ActivityCustomListView extends AppCompatActivity {

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

        //identify the custom list view container in activity layout file
        ListView mListView = (ListView)findViewById(R.id.customListViewContainer);

        //get array of data from database
        SQLLiteHelper db = new SQLLiteHelper(this);
        ArrayList<Records> recordsArray = db.getAllRecords();

        //call the custom adapter
        CustomListAdapter adapter = new CustomListAdapter(this, R.layout.custom_record,recordsArray);

        //set the listview to the adapter
        mListView.setAdapter(adapter);

    }
}



//********** CustomListAdapter.java**********

public class CustomListAdapter extends ArrayAdapter<Records>  {

    private Context mContext;
    private int mResource;

    private static class ViewHolder{
        TextView ID;
        TextView Name;
        TextView File;
        TextView Path;
        ImageView Photo;
    }

    public CustomListAdapter(Context context, int resource, ArrayList<Records>objects){
        super (context, resource, objects);
        mContext = context;
        mResource = resource;
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        String ID = getItem(position).getID();
        String NAME = getItem(position).getName();
        String FILE = getItem(position).getFile();
        String PATH = getItem(position).getPath();
        Bitmap photoAsBitmap = null;
        try {
            photoAsBitmap = getItem(position).getPicture();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (BadElementException e) {
            e.printStackTrace();
        }

        Records records = new Records(ID,NAME,FILE,PATH,photoAsBitmap);

        final View result;
        ViewHolder holder;

        if(convertView == null){
            LayoutInflater inflater = LayoutInflater.from(mContext);
            convertView = inflater.inflate(mResource, parent, false);
            holder = new ViewHolder();
            holder.ID = (TextView)convertView.findViewById(R.id.tvcID);
            holder.Name = (TextView)convertView.findViewById(R.id.tvcName);
            holder.File = (TextView)convertView.findViewById(R.id.tvcFile);
            holder.Path = (TextView)convertView.findViewById(R.id.tvcPath);
            holder.Photo = (ImageView)convertView.findViewById(R.id.ivcPicture);

            result = convertView;

            convertView.setTag(holder);
        }
        else{
            holder=(ViewHolder)convertView.getTag();
            result = convertView;
        }

        holder.ID.setText(records.getID());
        holder.Name.setText(records.getName());
        holder.File.setText(records.getFile());
        holder.Path.setText(records.getPath());
        try {
            holder.Photo.setImageBitmap(records.getPicture());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (BadElementException e) {
            e.printStackTrace();
        }
        return convertView;
    }
}


//********** Records.java**********

public class Records {

    private String ID;
    private String NAME;
    private String FILE;
    private String PATH;
    private Bitmap photoAsBitmap;

    public Records(String id, String name, String file, String path, Bitmap photoFILEasBitmap) {
        this.ID = id;
        this.NAME = name;
        this.FILE = file;
        this.PATH = path;
        this.photoAsBitmap = photoFILEasBitmap;
    }

    public String getID(){return ID;}

    public String getName(){return NAME;}

    public String getFile(){return FILE;}

    public String getPath(){return PATH;}

    public Bitmap getPicture() throws IOException, BadElementException {

        File photoFILEasFILE = new File(PATH);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        photoAsBitmap = BitmapFactory.decodeFile(String.valueOf(photoFILEasFILE), options);

        return photoAsBitmap;

    }

}
Matthew
  • 139
  • 1
  • 10