我正在使用一个扩展SherlockFragmentActivity的Activity,它有3个标签. 3个选项卡是实现LoaderManager.LoaderCallbacks的ListFragments. Activity的OnCreate方法像这样加载选项卡
bar.addTab(bar.newTab() .setTag("venues_List") .setText(getString(R.string.List_venues_header)) .setTabListener(new TabListener<VenueListFragment>( this, getString(R.string.List_invites_header), VenueListFragment.class, null)));// I do the EXACT same thing for the other two tabs, using their respective ListFragmentsif (savedInstanceState != null) { bar.setSelectednavigationItem(savedInstanceState.getInt("tab", 0));}
我正在加载标签的布局非常简单:
<?xml version="1.0" enCoding="utf-8"?><linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" androID:layout_wIDth="fill_parent" androID:layout_height="fill_parent" androID:orIEntation="vertical" ></linearLayout>
每个选项卡都有一个与此相同的类,只是称为不同的类:
import androID.content.Context;import androID.content.SharedPreferences;import androID.database.Cursor;import androID.os.Bundle;import androID.support.v4.app.LoaderManager;import androID.support.v4.content.Loader;import androID.support.v4.Widget.CursorAdapter;import androID.support.v4.Widget.SimpleCursorAdapter;import androID.vIEw.VIEw;import androID.Widget.AdapterVIEw;import androID.Widget.AdapterVIEw.OnItemClickListener;import androID.Widget.ListVIEw;import androID.Widget.Toast;import com.actionbarsherlock.app.SherlockListFragment;import com.lateral.oursvp.R;import com.lateral.oursvp.database.SimpleCursorLoader;import com.lateral.oursvp.database.VenuesDataSource;/** * @author rabbott * */public class VenueListFragment extends SherlockListFragment implements LoaderManager.LoaderCallbacks<Cursor> { SharedPreferences appPreferences; private CursorAdapter cursorAdapter; @OverrIDe public voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @OverrIDe public voID onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // bind the columns of the cursor to the List String[] from = new String[] { VenuesDataSource.KEY_name, VenuesDataSource.KEY_DESCRIPTION }; int[] to = new int[] { R.ID.List_item_Title, R.ID.List_item_subTitle }; cursorAdapter = new SimpleCursorAdapter( getActivity(), R.layout.List_item, null, from, to, 0); // retrIEve the ListvIEw to populate ListVIEw lv = (ListVIEw) getActivity().findVIEwByID(androID.R.ID.List); // set the adapter on the ListvIEw lv.setAdapter(cursorAdapter); // click event for each row of the List lv.setonItemClickListener(new OnItemClickListener() { public voID onItemClick(AdapterVIEw<?> arg0, VIEw vIEw, int position, long ID) { Cursor cursor = cursorAdapter.getCursor(); cursor.movetoposition(position); Toast.makeText(getActivity(), "Tapped row " + position + "!", Toast.LENGTH_SHORT).show(); } }); // Start out with a progress indicator. setListShown(false); // load the data getActivity().getSupportLoaderManager().initLoader(0, null, this); } public Loader<Cursor> onCreateLoader(int loaderID, Bundle args) { return new VenueCursorLoader(getActivity()); } public voID onl oadFinished(Loader<Cursor> loader, Cursor cursor) { cursorAdapter.swapCursor(cursor); // the List should Now be shown if (isResumed()) { setListShown(true); } else { setListShownNoAnimation(true); } } public voID onl oaderreset(Loader<Cursor> loader) { cursorAdapter.swapCursor(null); } public static final class VenueCursorLoader extends SimpleCursorLoader { Context mContext; public VenueCursorLoader(Context context) { super(context); mContext = context; } @OverrIDe public Cursor loadInBackground() { VenuesDataSource datasource = new VenuesDataSource(mContext); return datasource.getAllVenues(((EventActivity) mContext).getEventID()); } }}
它使用此处定义的SimpleCursorLoaded:
import androID.content.Context;import androID.database.Cursor;import androID.support.v4.content.AsyncTaskLoader;public abstract class SimpleCursorLoader extends AsyncTaskLoader<Cursor> { private Cursor mCursor; public SimpleCursorLoader(Context context) { super(context); } /* Runs on a worker thread */ @OverrIDe public abstract Cursor loadInBackground(); /* Runs on the UI thread */ @OverrIDe public voID deliverResult(Cursor cursor) { if (isreset()) { // An async query came in while the loader is stopped if (cursor != null) { cursor.close(); } return; } Cursor oldCursor = mCursor; mCursor = cursor; if (isstarted()) { super.deliverResult(cursor); } if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) { oldCursor.close(); } } /** * Starts an asynchronous load of the contacts List data. When the result is ready the callbacks * will be called on the UI thread. If a prevIoUs load has been completed and is still valID * the result may be passed to the callbacks immediately. * <p/> * Must be called from the UI thread */ @OverrIDe protected voID onStartLoading() { if (mCursor != null) { deliverResult(mCursor); } if (takeContentChanged() || mCursor == null) { forceLoad(); } } /** * Must be called from the UI thread */ @OverrIDe protected voID onStopLoading() { // Attempt to cancel the current load task if possible. cancelLoad(); } @OverrIDe public voID onCanceled(Cursor cursor) { if (cursor != null && !cursor.isClosed()) { cursor.close(); } } @OverrIDe protected voID onreset() { super.onreset(); // Ensure the loader is stopped onStopLoading(); if (mCursor != null && !mCursor.isClosed()) { mCursor.close(); } mCursor = null; }}
我遇到的问题是,当我选择说..第二个选项卡(第三个选项卡执行相同)时,它会尝试加载光标,但是当它尝试填充List_items时,我收到错误说
E/AndroIDRuntime(2055): java.lang.IllegalArgumentException: column 'GIVEN_VARIABLE' does not exist
在设置了几个断点后,我发现它试图使用的光标是来自第一个标签的光标,它在充气时加载很好,但显然没有被关闭,显然是在尝试再次使用,即使我(我想从getAllVenues()发送一个不同的光标
编辑:这是堆栈跟踪发送给我的最后一个地方
当我设置一些断点时,我可以看到这里提供的光标是来自第一个选项卡的光标,而不是Venue选项卡的光标.
编辑:VenuesDataSource代码显示getAllVenues方法
import org.Json.JsONArray;import org.Json.JsONException;import org.Json.JsONObject;import androID.content.ContentValues;import androID.content.Context;import androID.database.Cursor;import androID.database.sqlException;import androID.util.Log;/** * @author rabbott * */public class VenuesDataSource extends appsqliteHelper { public static final String table_name = "venues"; // venue columns public static final String KEY_name = "name"; public static final String KEY_DESCRIPTION = "description"; public static final String KEY_START_TIME = "start_time"; public static final String KEY_ADDRESS = "address"; public static final String KEY_CITY = "city"; public static final String KEY_STATE = "state"; public static final String KEY_ZIP = "postal_code"; public static final String KEY_LNG = "lng"; public static final String KEY_LAT = "lat"; public static final String KEY_PHONE = "phone"; public static String ColUMNS_VENUES[] = { DatabaseConstants.KEY_ROWID, DatabaseConstants.KEY_EVENT_ID, KEY_name, KEY_DESCRIPTION, KEY_START_TIME, KEY_ADDRESS, KEY_CITY, KEY_STATE, KEY_ZIP, KEY_LNG, KEY_LAT, KEY_PHONE, DatabaseConstants.KEY_CREATED_AT }; public static final String CREATE_STATEMENT = "CREATE table IF NOT EXISTS " + table_name + " (" + "_ID INTEGER PRIMARY KEY autoINCREMENT," + "event_ID INTEGER NOT NulL," + "name TEXT NOT NulL," + "description TEXT," + "start_time TEXT," + "address TEXT NOT NulL," + "city TEXT NOT NulL," + "state TEXT NOT NulL," + "postal_code TEXT," + "lat TEXT," + "lng TEXT," + "phone TEXT," + "created_at TEXT);"; public VenuesDataSource(Context context) { super(context); Log.i("VenueDataSource", "Constructor"); } // create a new contact locally public long createVenue(Integer venue_ID, Integer event_ID, String name, String description, String start_time, String address, String city, String state, String postal_code, String lat, String lng, String phone, String created_at) { ContentValues initialValues = new ContentValues(); initialValues.put(DatabaseConstants.KEY_ROWID, event_ID); initialValues.put(DatabaseConstants.KEY_EVENT_ID, event_ID); initialValues.put(KEY_name, name); initialValues.put(KEY_DESCRIPTION, description); initialValues.put(KEY_START_TIME, start_time); initialValues.put(KEY_ADDRESS, address); initialValues.put(KEY_CITY, city); initialValues.put(KEY_STATE, state); initialValues.put(KEY_ZIP, postal_code); initialValues.put(KEY_PHONE, phone); initialValues.put(KEY_LAT, lat); initialValues.put(KEY_LNG, lng); initialValues.put(DatabaseConstants.KEY_CREATED_AT, created_at); return getWritableDatabase().insert(table_name, null, initialValues); } // retrIEve a venue from the local database public Cursor getVenue(long rowID) throws sqlException { Cursor mCursor = getWritableDatabase().query(true, table_name, ColUMNS_VENUES, DatabaseConstants.KEY_ROWID + "=" + rowID, null, null, null, null, null); if (mCursor != null) { mCursor.movetoFirst(); } return mCursor; } // update a local venue public long updateVenue(Integer venue_ID, Integer event_ID, String name, String description, String start_time, String address, String city, String state, String postal_code, String lat, String lng, String phone) { ContentValues initialValues = new ContentValues(); initialValues.put(DatabaseConstants.KEY_EVENT_ID, event_ID); initialValues.put(KEY_name, name); initialValues.put(KEY_DESCRIPTION, description); initialValues.put(KEY_START_TIME, start_time); initialValues.put(KEY_ADDRESS, address); initialValues.put(KEY_CITY, city); initialValues.put(KEY_STATE, state); initialValues.put(KEY_ZIP, postal_code); initialValues.put(KEY_PHONE, phone); initialValues.put(KEY_LAT, lat); initialValues.put(KEY_LNG, lng); return getWritableDatabase().update(table_name, initialValues, "_ID=?", new String[] { Long.toString(venue_ID) }); } // delete a local venue public boolean deleteVenue(long rowID) { return (getWritableDatabase().delete(table_name, DatabaseConstants.KEY_ROWID + "=" + rowID, null) > 0); } // retrIEve all local venues public Cursor getAllVenues(long event_ID) { Cursor mCursor = getWritableDatabase().query(true, table_name, ColUMNS_VENUES, DatabaseConstants.KEY_EVENT_ID + "=" + event_ID, null, null, null, null, null); return mCursor; } public boolean venueExists(int venue_ID) { Cursor mCursor = getWritableDatabase().query(true, table_name, ColUMNS_VENUES, DatabaseConstants.KEY_ROWID + "=" + venue_ID, null, null, null, null, null); if (mCursor.getCount() == 0) { mCursor.close(); return false; } else { mCursor.close(); return true; } } public voID parseVenue(JsONObject venueJson) throws JsONException { boolean venue_exists = false; int event_ID, venue_ID; String venue_name, venue_description, start_time, venue_address, venue_city, venue_state, venue_postal_code, lat, lng, venue_phone, created_at; venue_ID = venueJson.getInt(DatabaseConstants.KEY_REMOTE_ID); event_ID = venueJson.getInt(DatabaseConstants.KEY_EVENT_ID); venue_name = venueJson.getString(KEY_name); venue_description = venueJson.getString(KEY_DESCRIPTION); start_time = venueJson.getString(KEY_START_TIME); venue_address = venueJson.getString(KEY_ADDRESS); venue_city = venueJson.getString(KEY_CITY); venue_state = venueJson.getString(KEY_STATE); venue_postal_code = venueJson.getString(KEY_ZIP); venue_phone = venueJson.getString(KEY_PHONE); lat = venueJson.getString(KEY_LAT); lng = venueJson.getString(KEY_LNG); created_at = venueJson.getString(DatabaseConstants.KEY_CREATED_AT); // check to see if this venue already exists venue_exists = this.venueExists(venue_ID); if (venue_exists == true) { this.updateVenue( venue_ID, event_ID, venue_name, venue_description, start_time, venue_address, venue_city, venue_state, venue_postal_code, lat, lng, venue_phone); } else { this.createVenue( venue_ID, event_ID, venue_name, venue_description, start_time, venue_address, venue_city, venue_state, venue_postal_code, lat, lng, venue_phone, created_at); } } public voID parseVenues(JsONArray venuesArray) throws JsONException { JsONObject venueJson; for (int i = 0; i < venuesArray.length(); i++) { // Iterate through each venue venueJson = venuesArray.getJsONObject(i); this.parseVenue(venueJson); } }}
解决方法:
问题是initLoader方法的第一个参数是唯一标识要加载的每个项目的方法,我的所有项目都设置为相同的(0)值 – 将它们更改为修复问题的唯一值.
总结以上是内存溢出为你收集整理的android – 具有多个ListFragments和SQLite游标战斗的SherlockFragmentActivity全部内容,希望文章能够帮你解决android – 具有多个ListFragments和SQLite游标战斗的SherlockFragmentActivity所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)