Search code examples
androidandroid-spinnerandroid-adapterandroid-cursorloader

null cursor in custom adapter?


I'm having an issue that I just can't seem to trace down the cause of. This may be simply due to my lack of familiarity with loaders...

I have a custom adapter I use to set a prompt for a spinner in the "closed" position (single line display) until the first selection is made. I've used this before with great success, but this time it's not working. The only difference is that now I'm using loaders.

When the adapter tries to access the cursor in my overridden getView method, the cursor is null and of course I get a force close with a null pointer exception. I don't understand how the cursor can be null there as obviously the getDropDownView method (which I don't override) has access to the cursor as the dropdown is populated...

All I can think is that for some reason the getView method is retaining the original null that is passed in as a placeholder while the loader does it's work. I would think that when I use changeCursor that reference would change as well, but it seems that it isn't.

main activity adapter call

adapter = new CursorAdapter_SpinnerPrompt(this,
    R.layout.rowlayout_black, null, new String[] { ThreadMillDB.THREADMILL_THREAD }, new int[] { R.id.ListItem });
mThreadChooser.setAdapter(adapter);

relevant loader code

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    adapter.changeCursor(cursor);
}

adapter code

public class CursorAdapter_SpinnerPrompt extends SimpleCursorAdapter {
    private Context context;
    private int layout;
    private Cursor c;
    private String[] from;
    private int[] to;
    public static boolean spinnerFlag = false;

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null)
            convertView = View.inflate(context, layout, null);
        if (spinnerFlag != false) {
            c.moveToPosition(position);          // cursor is null here... why?  How to fix?
            TextView tv = (TextView) convertView;
            tv.setText(c.getString(c.getColumnIndex(ThreadMillDB.THREADMILL_THREAD)));
        } else {
            TextView tv = (TextView) convertView;
            tv.setText("Choose a thread");
            tv.setTextColor(Color.parseColor("#778899"));
        }
        return convertView;
    }
}

UPDATE

And of course in typing this out I figured out a solution. I moved the creation of the adapter out of my activity onCreate and into onLoadFinished and put the cursor into the call. However, this seems messier than the way I was trying to do it. Is there any modification I can make to my original methods (shown above) to make it work without having to move the adapter instantiation to the onLoadFinished method?


Solution

  • your suspicious is correct.

    The cursor reference you remembered on your constructor is not the same that you passed on chageCursor(Cursor c). The proper way to get the cursor on a CursorAdapter is calling getCursor() than you'll get the reference to the cursor you passed on changeCursor(Cursor c).