I'm implementing a ExpandableListView and for each group, it shows the childs, and each child with its own duration, and the group shows the sum of all the durations of the childs.
However, when I click a child it shows the error:
Couldn't read row 1, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
And I'm not calling the method setOnChildClickListener
. And even if I call it, when I click the child, it doesn't stop on it when I put a breakpoint.
This is the problem, I can't find where the error is since the stacktrace doesn't point to my project's classes, but to android native's class. I've tried putting breakpoints in every part of my code, but when I click a child, none of the breakpoints are reached.
By the way, I'm using the ViewHolder pattern to deal with the views, and the adapter is a CursorTreeAdapter
Here is my code - and the full stacktrace is at the end:
public class MyClass extends ExpandableListActivity
{
private Cursor mContactsCursor;
private ExpandableListView mExpandableListView;
private Integer mContactId;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.contacts_layout);
mExpandableListView.setOnGroupClickListener(new OnGroupClickListener()
{
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id)
{
mContactId = Integer.parseInt(v.getTag(R.id.contact_name).toString());
return false;
}
});
}
@Override
public void onResume()
{
super.onResume();
mContactsCursor = mController.getContacts();
mExpandableListView.setAdapter(new ContactsExpandableListAdapter(mContactsCursor, this));
}
@Override
public void onPause()
{
super.onPause();
if(!mContactsCursor.isClosed())
mContactsCursor.close();
}
@Override
public void onDestroy()
{
super.onDestroy();
if(!mContactsCursor.isClosed())
mContactsCursor.close();
}
public class ContactsExpandableListAdapter extends CursorTreeAdapter
{
private TextView mContactNameTextView, mContactNumberTextView, mDurationTextView;
public ContactsExpandableListAdapter(Cursor cursor, Context context)
{
super(cursor, context);
}
@Override
protected Cursor getChildrenCursor(Cursor groupCursor)
{
return mController.getContactById(mContactId);
}
@Override
protected View newGroupView(Context context, Cursor cursor, boolean isExpanded, ViewGroup viewGroup)
{
View view = LayoutInflater.from(context).inflate(R.layout.listitem_contacts, viewGroup, false);
ViewHolder viewHolder = new ViewHolder();
viewHolder.contactName = (TextView) view.findViewById(R.id.contact_name);
viewHolder.duration = (TextView) view.findViewById(R.id.duration);
viewHolder.groupIndicator = (ImageView) view.findViewById(R.id.indicator_icon);
viewHolder.contactName.setText(cursor.getString(cursor.getColumnIndex("contact_name")));
// Set the duration to the view
viewHolder.duration.setText(cursor.getString(cursor.getColumnIndex("duration_sum")));
// Set the tags to the view to be used later when the user click the group view.
// These tags are the contact number, contact id and the the view holder object
// to be retrieved when binding the group view
view.setTag(R.id.contact_number, cursor.getString(cursor.getColumnIndex("contact_number")));
view.setTag(R.id.rlt_main, viewHolder);
view.setTag(R.id.contact_name, cursor.getString(cursor.getColumnIndex("contact_id")));
}
return view;
}
@Override
protected View newChildView(Context context, Cursor cursor, boolean isLastChild, ViewGroup viewGroup)
{
View view = LayoutInflater.from(context).inflate(R.layout.listitem_contacts, viewGroup, false);
mContactNumberTextView = (TextView) view.findViewById(R.id.phone_number);
mContactNumberTextView.setText(cursor.getString(cursor.getColumnIndex("contact_name")));
mDurationTextView = (TextView) view.findViewById(R.id.duration);
mDurationTextView.setText(cursor.getString(cursor.getColumnIndex("duration")));
view.setTag(cursor.getString(cursor.getColumnIndex("contact_number")));
return view;
}
@Override
protected void bindGroupView(View view, Context context, Cursor cursor, boolean isExpanded)
{
ViewHolder viewHolder = (ViewHolder) view.getTag(R.id.rlt_main);
// For each view created, make a query to the database based on the contact id.
// This is not very wise to do, but will probably be changed in the future.
Integer contactId = cursor.getInt(cursor.getColumnIndex("contact_id"));
// Check if the current contact id is equal to -1. If yes it means the contact
Cursor currentContactCursor = mFilterByContactController.getContactById(contactId);
// Check if the cursor being retrieved from the database based on the current view cursor
// is major than zero. If yes, it means it has children, so set the indicator icon to this
// view as visible. If not, set the indicator for this view as gone.
if(currentContactCursor != null && currentContactCursor.getCount() > 0)
{
viewHolder.groupIndicator.setVisibility(View.VISIBLE);
viewHolder.groupIndicator.setImageResource(isExpanded ? R.drawable.expander_ic_maximized : R.drawable.expander_ic_minimized);
}
else
{
viewHolder.groupIndicator.setVisibility(View.GONE);
}
if(cursor.getString(cursor.getColumnIndex("contact_name")) == null)
viewHolder.contactName.setText(cursor.getString(cursor.getColumnIndex("contact_number")));
else
viewHolder.contactName.setText(cursor.getString(cursor.getColumnIndex("contact_name")));
// Set the duration to the view
viewHolder.duration.setText(Utils.convertTime(Integer.parseInt(cursor.getString(cursor.getColumnIndex("duration_sum")))));
// Set the tags to the view to be used later when the user click the group view
view.setTag(R.id.contact_number, cursor.getString(cursor.getColumnIndex("contact_number")));
view.setTag(R.id.contact_name, cursor.getString(cursor.getColumnIndex("contact_id")));
if(!currentContactCursor.isClosed())
currentContactCursor.close();
}
}
@Override
protected void bindChildView(View view, Context context, Cursor cursor, boolean expanded)
{
try
{
if(cursor.getString(cursor.getColumnIndex("contact_name")) == null)
{
mContactNameTextView = (TextView) view.findViewById(R.id.contact_name);
mContactNameTextView.setText(cursor.getString(cursor.getColumnIndex("phone_number")));
}
else
{
mContactNumberTextView = (TextView) view.findViewById(R.id.phone_number);
mContactNumberTextView.setText(cursor.getString(cursor.getColumnIndex("contact_number")));
}
mDurationTextView = (TextView) view.findViewById(R.id.duration);
mDurationTextView.setText(cursor.getString(cursor.getColumnIndex("duration")));
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
if(cursor.isClosed())
cursor.close();
}
}
}
Full stacktrace
07-22 16:47:46.388: E/AndroidRuntime(7718): java.lang.IllegalStateException: Couldn t read row 1, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.database.CursorWindow.nativeGetLong(Native Method)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.database.CursorWindow.getLong(CursorWindow.java:515)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.widget.CursorTreeAdapter$MyCursorHelper.getId(CursorTreeAdapter.java:436)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.widget.CursorTreeAdapter.getChildId(CursorTreeAdapter.java:173)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.widget.ExpandableListConnector.getItemId(ExpandableListConnector.java:427)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.widget.AdapterView.getItemIdAtPosition(AdapterView.java:756)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.widget.AdapterView.setSelectedPositionInt(AdapterView.java:1128)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.widget.AbsListView.onTouchEvent(AbsListView.java:3147)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.View.dispatchTouchEvent(View.java:5541)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1951)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1712)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726)
07-22 16:47:46.388: E/AndroidRuntime(7718): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1912)
07-22 16:47:46.388: E/AndroidRuntime(7718): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1371)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.app.Activity.dispatchTouchEvent(Activity.java:2364)
07-22 16:47:46.388: E/AndroidRuntime(7718): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1860)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.View.dispatchPointerEvent(View.java:5721)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:2890)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2466)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewRootImpl.processInputEvents(ViewRootImpl.java:845)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2475)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.os.Handler.dispatchMessage(Handler.java:99)
07-22 16:47:46.388: E/AndroidRuntime(7718): at android.os.Looper.loop(Looper.java:137) 07-22 16:47:46.388: E/AndroidRuntime(7718): at android.app.ActivityThread.main(ActivityThread.java:4424)
07-22 16:47:46.388: E/AndroidRuntime(7718): at java.lang.reflect.Method.invokeNative(Native Method)
07-22 16:47:46.388: E/AndroidRuntime(7718): at java.lang.reflect.Method.invoke(Method.java:511)
07-22 16:47:46.388: E/AndroidRuntime(7718): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
07-22 16:47:46.388: E/AndroidRuntime(7718): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
07-22 16:47:46.388: E/AndroidRuntime(7718): at dalvik.system.NativeStart.main(Native Method)
if(..) {
didn't get copied... – DammarBaseColumns#_ID
) and not finding it in the cursor? Which columns are you using inmContactsCursor
- you haven't forgotten the row id in that? – Endive