Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Images in SimpleCursorAdapter

I'm trying to use a SimpleCursorAdapter with a ViewBinder to get an image from the database and put it into my ListView item view. Here is my code:

private void setUpViews() {
    mNewsView = (ListView) findViewById(R.id.news_list);

    Cursor cursor = getNews();
    SimpleCursorAdapter curAdapter = new SimpleCursorAdapter(
            getApplicationContext(), R.layout.cursor_item, cursor,
            new String[] { "title", "content", "image" },
            new int[] { R.id.cursor_title, R.id.cursor_content,
                    R.id.news_image });
    
    ViewBinder viewBinder = new ViewBinder() {
        
        public boolean setViewValue(View view, Cursor cursor,
                int columnIndex) {
            ImageView image = (ImageView) view;
            byte[] byteArr = cursor.getBlob(columnIndex);
            image.setImageBitmap(BitmapFactory.decodeByteArray(byteArr, 0, byteArr.length));
            return true;
        }
    };
    ImageView image = (ImageView) findViewById(R.id.news_image);
    viewBinder.setViewValue(image, cursor, cursor.getColumnIndex("image"));
    curAdapter.setViewBinder(viewBinder);
    mNewsView.setAdapter(curAdapter);
}

I am getting:

android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 60

while executing byte[] byteArr = cursor.getBlob(columnIndex);. Does anyone have an idea what am I doing wrong?

like image 907
SSemashko Avatar asked Jul 15 '11 16:07

SSemashko


2 Answers

I extended SimpleCursorAdapter, and while I did not use a ViewBinder here is my code for using an image stored as a blob in an sqlite database in a listview. This was adapted from an article I read here.

My layout file for a row is:

row_layout_two_line.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/select_item">

<ImageView 
    android:id="@+id/pic"
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:layout_marginLeft="10dp"
    android:contentDescription="@string/imagedesc"
    android:src="@drawable/icon"
    android:layout_gravity="center_vertical">
</ImageView>

<LinearLayout
    android:id="@+id/linearLayout0"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical" 
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@+id/label"
            android:textStyle="bold"
            android:textColor="#000"
            android:textSize="20sp" >
        </TextView>

        <TextView
            android:id="@+id/label1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:text="@+id/label1"
            android:textStyle="bold"
            android:textColor="#000"
            android:textSize="20sp" >
        </TextView>

    </LinearLayout>

    <TextView
        android:id="@+id/label2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="35dp"
        android:text="@+id/label2"
        android:textColor="#000"
        android:textSize="15sp" >
    </TextView>
</LinearLayout>

enter image description here

The calling code

...
    adapter = null;
    mCursor = search();

    startManagingCursor(mCursor);
    // Now create a new list adapter bound to the cursor.
    BaseAdapter adapter = new ImageCursorAdapter(this, // Context.
            R.layout.row_layout_two_line, // Specify the row template
                                                    // to use (here, two
                                                    // columns bound to the
                                                    // two retrieved cursor
                                                    // rows).
            mCursor, // Pass in the cursor to bind to.
            // Array of cursor columns to bind to.
            new String [] {"personImage", "firstName", "lastName", "title"},
            // Parallel array of which template objects to bind to those
            // columns.
            new int[] { R.id.pic, R.id.label, R.id.label1, R.id.label2 });


    // Bind to our new adapter.
    setListAdapter(adapter);
...

ImageCursorAdapter.java

import android.content.Context;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;

public class ImageCursorAdapter extends SimpleCursorAdapter {

    private Cursor c;
    private Context context;

public ImageCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
    super(context, layout, c, from, to);
    this.c = c;
    this.context = context;
}

public View getView(int pos, View inView, ViewGroup parent) {
       View v = inView;
       if (v == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inflater.inflate(R.layout.row_layout_two_line, null);
       }
       this.c.moveToPosition(pos);      
       String firstName = this.c.getString(this.c.getColumnIndex("firstName"));
       String lastName = this.c.getString(this.c.getColumnIndex("lastName"));
       String titleStr = this.c.getString(this.c.getColumnIndex("title"));
       byte[] image = this.c.getBlob(this.c.getColumnIndex("personImage"));
       ImageView iv = (ImageView) v.findViewById(R.id.pic);
       if (image != null) {
           // If there is no image in the database "NA" is stored instead of a blob 
           // test if there more than 3 chars "NA" + a terminating char if more than
           // there is an image otherwise load the default
           if(image.length > 3)
           {
               iv.setImageBitmap(BitmapFactory.decodeByteArray(image, 0, image.length));
           }
           else
           {
               iv.setImageResource(R.drawable.icon);
           }
       }
           TextView fname = (TextView) v.findViewById(R.id.label);
           fname.setText(firstName);

           TextView lname = (TextView) v.findViewById(R.id.label1);
           lname.setText(lastName);

           TextView title = (TextView) v.findViewById(R.id.label2);
           title.setText(titleStr);
       return(v);
}

}

Here is what it looks like in the end

enter image description here

like image 184
Daniel Jamison Avatar answered Oct 24 '22 04:10

Daniel Jamison


I think the cursor.moveToFirst() has not been called so the cursor is throwing android.database.CursorIndexOutOfBoundsException.

Before using a cursor you should always check is the cursor is empty or not by calling cursor.moveToFirst(). This will also position the cursor at the first position.

like image 30
Ankur Kumar Avatar answered Oct 24 '22 04:10

Ankur Kumar