android - ListView in ListFragment not Loading Items -
i have listfragment custom cursoradapter connected database. items in database not appearing in listview, including listheader, , instead see spinning wheel.
i had app working fine simplecursoradapter in listfragment before. have tested on non-empty databases. clue have why not working following error in logcat when try "delete all" option in contextactionmenu.
viewrootimpl senduseractionevent() == null
here listfragment:
import com.actionbarsherlock.app.sherlocklistfragment; import com.actionbarsherlock.view.actionmode; import com.actionbarsherlock.view.actionmode.callback; import com.actionbarsherlock.view.menu; import com.actionbarsherlock.view.menuinflater; import com.actionbarsherlock.view.menuitem; import info.mariegrap.dancejournal.r.id; import info.mariegrap.database.dancecontentprovider; import info.mariegrap.database.dancedatabasehelper; import info.mariegrap.database.stylecursoradapter; import info.mariegrap.database.styletable; import info.mariegrap.model.style; import android.app.activity; import android.content.contentvalues; import android.content.context; import android.net.uri; import android.os.bundle; import android.support.v4.app.loadermanager; import android.support.v4.content.cursorloader; import android.support.v4.content.loader; import android.util.log; import android.view.view; import android.widget.adapterview; import android.widget.adapterview.onitemlongclicklistener; import android.widget.listview; import android.database.cursor; import android.database.sqlexception; public class stylefragment extends sherlocklistfragment implements loadermanager.loadercallbacks<cursor>{ private static final int loader_id = 0; private context context; private onstyleselectedlistener callback; private stylecursoradapter styleadapter; private dancedatabasehelper mydbhelper; private callback mactionmodecallback; private actionmode mactionmode; private long selectedid; @override public void onactivitycreated(bundle savedinstancestate){ super.onactivitycreated(savedinstancestate); context = this.getactivity(); sethasoptionsmenu(true); //setretaininstance(true); this.getlistview().setbackgroundcolor(getresources().getcolor(r.color.style_background)); //this.getlistview().setdividerheight(0); this.getlistview().setscrollingcacheenabled(true); this.getlistview().addheaderview(new listheader(context, this.getresources().getstring(r.string.list_header_style_title), this.getresources().getstring(r.string.list_header_style_subtitle))); this.setactionmodecallback(); this.setlongclicklistener(); /*mydbhelper = new dancedatabasehelper(this.context, null, null, 1); try { mydbhelper.opendatabase();; }catch(sqlexception sqle){ throw sqle; }*/ this.styleadapter = new stylecursoradapter(context, null, 0); getloadermanager().initloader(loader_id, null, this); this.getlistview().setadapter(this.styleadapter); log.d("mgrap", "adapter: " + styleadapter); } @override public void onattach(activity activity) { super.onattach(activity); try { callback = (onstyleselectedlistener) activity; } catch (classcastexception e) { throw new classcastexception(activity.tostring() + " must implement onstyleselectedlistener"); } } @override public void onlistitemclick(listview l, view v, int position, long id){ if (position == 0){ return; } this.setlistadapter(null); this.getlistview().getchildat(position); callback.onstyleselected(position); } public interface onstyleselectedlistener { /** called stylefragment when list item selected */ public void onstyleselected(int position); } @override public void oncreateoptionsmenu(menu menu, menuinflater inflater) { inflater.inflate(r.menu.style_actionbar, menu); } @override public boolean onoptionsitemselected(menuitem item) { switch (item.getitemid()) { case r.id.style_add: contentvalues cv = new contentvalues(); cv.put(styletable.style_key_name, "tada!"); uri uri = uri.parse("content://info.mariegrap.dancejournal.provider/style_table/0"); uri iduri = context.getcontentresolver().insert(uri, cv); //styleadapter.notifydatasetchanged(); filldata(); return true; case r.id.style_delete_all: uri delete_uri = uri.parse("content://info.mariegrap.dancejournal.provider/style_table"); context.getcontentresolver().delete(delete_uri, null, null); //styleadapter.notifydatasetchanged(); filldata(); return true; default: return super.onoptionsitemselected(item); } } protected void filldata() { this.getsherlockactivity().getsupportloadermanager().restartloader(loader_id, null, this); this.getlistview().setadapter(styleadapter); } protected void deletestyle(long id) { uri uri = uri.parse("content://info.mariegrap.dancejournal.provider/style_table/" + id); this.getsherlockactivity().getcontentresolver().delete(uri, null, null); //styleadapter.notifydatasetchanged(); filldata(); } @override public loader<cursor> oncreateloader(int id, bundle args) { string[] projection = { styletable.style_key_id, styletable.style_key_name }; return new cursorloader(this.context, dancecontentprovider.content_uri_style, projection, null, null, null); } @override public void onloadfinished(loader<cursor> loader, cursor data) { styleadapter.swapcursor(data); } @override public void onloaderreset(loader<cursor> loader) { styleadapter.swapcursor(null); } private void setactionmodecallback(){ mactionmodecallback = new callback() { @override public boolean oncreateactionmode(actionmode mode, menu menu) { menuinflater inflater = mode.getmenuinflater(); inflater.inflate(r.menu.style_context_menu, menu); return true; } @override public boolean onprepareactionmode(actionmode mode, menu menu) { return false; } @override public boolean onactionitemclicked(actionmode mode, menuitem item) { switch (item.getitemid()) { case r.id.style_delete: deletestyle(selectedid); mode.finish(); return true; default: return false; } } @override public void ondestroyactionmode(actionmode mode) { mactionmode = null; } }; } private void setlongclicklistener(){ this.getlistview().setonitemlongclicklistener (new onitemlongclicklistener() { public boolean onitemlongclick(adapterview<?> parent, view view, int position, long id) { if (mactionmode != null || position == 0) { return false; } mactionmode = getsherlockactivity().startactionmode(mactionmodecallback); selectedid = id; return true; } }); } }
here custom cursoradapter:
import view.stylelistitem; import info.mariegrap.model.style; import android.content.context; import android.database.cursor; import android.support.v4.widget.cursoradapter; import android.util.log; import android.view.view; import android.view.viewgroup; public class stylecursoradapter extends cursoradapter { public stylecursoradapter(context context, cursor c, int flags) { super(context, c, flags); } @override public void bindview(view arg0, context arg1, cursor arg2) { int id = arg2.getint(styletable.style_col_id); string name = arg2.getstring(styletable.style_col_name); style style = new style(name, id); stylelistitem listitem = (stylelistitem) arg0; listitem.setstyle(style); } @override public view newview(context arg0, cursor arg1, viewgroup arg2) { int id = arg1.getint(styletable.style_col_id); string name = arg1.getstring(styletable.style_col_name); style style = new style(name, id); stylelistitem listitem = new stylelistitem(arg0, style); listitem.setstyle(style); log.d("mgrap", "adapter view: " + listitem.getstyleid()); return listitem; } }
here listitem view:
public class stylelistitem extends linearlayout { private textview styleview; private style style; public stylelistitem(context context, style style) { super(context); layoutinflater inflater = (layoutinflater)context.getsystemservice(context.layout_inflater_service); inflater.inflate(r.layout.style_row, this, true); styleview = (textview)findviewbyid(r.id.style_label); log.d("mgrap", "style view: " + styleview); setstyle(style); } public void setstyle(style style) { this.style = style; displaystyle(this.style); } public style getstyle(){ return style; } private void displaystyle(style style) { if (style != null) { styleview.settext(style.getname()); } } public int getstyleid() { return styleview.getid(); } }
here layout xml list items:
<?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="wrap_content" > <imageview android:id="@+id/icon" android:layout_width="30dp" android:layout_height="24dp" android:layout_marginleft="4dp" android:layout_marginright="8dp" android:layout_margintop="8dp" android:src="@drawable/ic_launcher" > </imageview> <textview android:id="@+id/style_label" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="6dp" android:lines="1" android:text="@+id/textview01" android:textsize="24sp" > </textview> </linearlayout>
here xml layout list header:
<?xml version="1.0" encoding="utf-8"?> <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/list_header_background_color" android:layout_marginbottom="5dip" > <linearlayout android:layout_height="wrap_content" android:layout_width="wrap_content" android:orientation="vertical" android:paddingtop="5dip" android:paddingleft="10dip" android:paddingbottom="13dip" android:layout_centervertical="true" android:layout_alignparentleft="true"> <textview android:id="@+id/listview_header_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/list_header_style_title" android:textsize="17sp" android:textstyle="bold" android:textcolor="@color/list_header_title_color" /> <textview android:id="@+id/listview_header_subtitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/list_header_style_subtitle" android:textsize="13sp" android:textcolor="@color/list_header_subtitle_color" /> </linearlayout> <imageview android:id="@+id/list_header_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerhorizontal="true" android:layout_alignparentright="true" android:layout_marginright="20dp" android:layout_margintop="5dp" android:layout_marginbottom="13dp" android:visibility="gone" android:contentdescription="@string/image_desc" /> </relativelayout>
and here class defines style database table:
import android.database.sqlite.sqlitedatabase; import android.util.log; public class styletable { /** style table in database. */ public static final string table_style = "style_table"; /** style table column names , ids database access. */ public static final string style_key_id = "_id"; public static final int style_col_id = 0; public static final string style_key_name = "name"; public static final int style_col_name = style_col_id + 1; /** sqlite database creation statement. auto-increments ids of inserted * styles. style ids set after insertion database. */ public static final string database_create = "create table " + table_style + " (" + style_key_id + " integer primary key autoincrement, " + style_key_name + " text);"; /** sqlite database table removal statement. used if upgrading * database. */ public static final string database_drop = "drop table if exists " + table_style; /** * initializes database. * * @param database * database initialize. */ public static void oncreate(sqlitedatabase database) { database.execsql(database_create); } /** * upgrades database new version. * * @param database * database upgrade. * @param oldversion * old version of database. * @param newversion * new version of database. */ public static void onupgrade(sqlitedatabase database, int oldversion, int newversion) { log.w("mgrap", "updating database..."); database.execsql(database_drop); oncreate(database); } }
it's hard without having more logging go with, there couple things jump out:
- the adapter being set on list view directly instead of calling
setadapter
on listfragment. causes problems. - you're setting list view's adapter after initializing loader. might not race condition since callbacks called in main loop after call finished, wouldn't count on it.
Comments
Post a Comment