SherlockFragmentActivity多ListFragments和SQLite光标战斗 [英] SherlockFragmentActivity with multiple ListFragments and SQLite cursor battles

查看:296
本文介绍了SherlockFragmentActivity多ListFragments和SQLite光标战斗的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的一个延伸活动 SherlockFragmentActivity ,有3个标签。 3选项卡的 ListFragments 实现的 LoaderManager.LoaderCallbacks 。该活动的onCreate方法加载标签,像这样

  bar.addTab(bar.newTab()
    .setTag(venues_list)
    .setText(的getString(R.string.list_venues_header))
    .setTabListener(新TabListener< VenueListFragment>(
        对此,的getString(R.string.list_invites_header),VenueListFragment.class,NULL)));//我做同样的事情对于其他两个选项卡,使用各自的ListFragments如果(savedInstanceState!= NULL){
    bar.setSelectedNavigationItem(savedInstanceState.getInt(标签,0));
}

这是我加载的卡口插入布局很简单:

 <?XML版本=1.0编码=UTF-8&GT?;
< LinearLayout中的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =FILL_PARENT
    机器人:layout_height =FILL_PARENT
    机器人:方向=垂直>< / LinearLayout中>

每个选项卡中有一类是相同的这个,就叫做不同的东西:

 进口android.content.Context;
进口android.content.Shared preferences;
进口android.database.Cursor;
进口android.os.Bundle;
进口android.support.v4.app.LoaderManager;
进口android.support.v4.content.Loader;
进口android.support.v4.widget.CursorAdapter;
进口android.support.v4.widget.SimpleCursorAdapter;
进口android.view.View;
进口android.widget.AdapterView;
进口android.widget.AdapterView.OnItemClickListener;
进口android.widget.ListView;
进口android.widget.Toast;进口com.actionbarsherlock.app.SherlockListFragment;
进口com.lateral.oursvp.R;
进口com.lateral.oursvp.database.SimpleCursorLoader;
进口com.lateral.oursvp.database.VenuesDataSource;/ **
 * @author rabbott
 *
 * /
公共类VenueListFragment扩展SherlockListFragment实现LoaderManager.LoaderCallbacks<&光标GT; {
    共享preferences应用preferences;    私人的CursorAdapter的CursorAdapter;    @覆盖
    公共无效的onCreate(捆绑savedInstanceState){
        super.onCreate(savedInstanceState);
    }    @覆盖
    公共无效onActivityCreated(捆绑savedInstanceState){
        super.onActivityCreated(savedInstanceState);        //光标的列结合到列表
        的String [] =由新的String [] {VenuesDataSource.KEY_NAME,VenuesDataSource.KEY_DESCRIPTION};
        INT []为= INT新[] {R.id.list_item_title,R.id.list_item_subtitle};        CursorAdapter的=新SimpleCursorAdapter(getActivity(),R.layout.list_item,空,发件人,收件人,0);        //检索列表视图来填充
        。ListView的LV =(ListView控件)getActivity()findViewById(android.R.id.list);        //设置适配器上的列表视图
        lv.setAdapter(CursorAdapter的);        //点​​击事件列表中的每个行
        lv.setOnItemClickListener(新OnItemClickListener(){            公共无效onItemClick(适配器视图<>为arg0,观景,
                    INT位置,长的id){
                光标光标= cursorAdapter.getCursor();
                cursor.moveToPosition(位置);                Toast.makeText(getActivity(),行螺纹+位置+,Toast.LENGTH_SHORT!).show();
            }
        });        //显示进度指示器开始了。
        setListShown(假);        //加载数据
        。getActivity()getSupportLoaderManager()initLoader(0,null,则此)。
    }    公共装载机<&光标GT; onCreateLoader(INT loaderId,捆绑参数){
        返回新VenueCursorLoader(getActivity());
    }    公共无效onLoadFinished(装载机<&光标GT;装载机,光标光标){
        cursorAdapter.swapCursor(光标);        //列表现在应该表现
        如果(isResumed()){
            setListShown(真);
        }其他{
            setListShownNoAnimation(真);
        }
    }    公共无效onLoaderReset(装载机<&光标GT;装载机){
        cursorAdapter.swapCursor(NULL);
    }    公共静态最后一类VenueCursorLoader扩展SimpleCursorLoader {        上下文mContext;        公共VenueCursorLoader(上下文的背景下){
            超级(上下文);            mContext =背景;
        }        @覆盖
        公共光标loadInBackground(){
            VenuesDataSource数据源=新VenuesDataSource(mContext);            返回datasource.getAllVenues(((EventActivity)mContext).getEventId());
        }    }
}

它使用的 SimpleCursorLoaded 定义如下:

 进口android.content.Context;
进口android.database.Cursor;
进口android.support.v4.content.AsyncTaskLoader;公共抽象类SimpleCursorLoader扩展AsyncTaskLoader<&光标GT; {
    私人光标mCursor;    公共SimpleCursorLoader(上下文的背景下){
        超级(上下文);
    }    / *运行在一个工作线程* /
    @覆盖
    公共抽象光标loadInBackground();    / *运行在UI线程* /
    @覆盖
    公共无效deliverResult(光标光标){
        如果(isReset()){
            //异步查询进来,而装载器停止
            如果(指针!= NULL){
                cursor.close();
            }
            返回;
        }
        光标oldCursor = mCursor;
        mCursor =光标;        如果(isStarted()){
            super.deliverResult(光标);
        }        如果(oldCursor = NULL&放大器;!&安培; oldCursor =光标和放大器;!&安培;!oldCursor.isClosed()){
            oldCursor.close();
        }
    }    / **
     *启动联系人列表数据的异步加载。当结果准备好回调
     *将在UI线程调用。如果previous负荷已经完成,仍然有效
     *结果可以立即传递给回调。
     * LT; P />
     *必须从UI线程调用
     * /
    @覆盖
    保护无效onStartLoading(){
        如果(mCursor!= NULL){
            deliverResult(mCursor);
        }
        如果(takeContentChanged()|| mCursor == NULL){
            的forceload();
        }
    }    / **
     *必须从UI线程调用
     * /
    @覆盖
    保护无效onStopLoading(){
        //尝试如果可能的话,取消当前的负载任务。
        cancelLoad();
    }    @覆盖
    公共无效onCanceled(光标光标){
        如果(光标=空&放大器;!&放大器;!cursor.isClosed()){
            cursor.close();
        }
    }    @覆盖
    保护无效onReset(){
        super.onReset();        //确保装载机停止
        onStopLoading();        如果(mCursor =空&放大器;!&放大器;!mCursor.isClosed()){
            mCursor.close();
        }
        mCursor = NULL;
    }
}

我遇到的问题是,当我选择说..第二个选项卡(第三个选项卡不相同),它会尝试加载光标,但是,当它试图填充list_items,我得到一个错误说

  E / AndroidRuntime(2055):java.lang.IllegalArgumentException异常:列'GIVEN_VARIABLE'不存在

设定我们已经发现,光标其试图使用不同于第一标签,其中装上通货膨胀细光标,但显然是没有得到关闭,并​​且显然试图甚至被再次使用几个断点之后虽然我(觉得)我送它getAllVenues不同的光标()

编辑:这是最后的地方的堆栈跟踪送我
当我设置一些断点我可以看到,这里正在提供的光标,是从第一个选项卡中的游标,而不是该地点标签..

编辑:VenuesDataSource code显示getAllVenues方法

 进口org.json.JSONArray;
进口org.json.JSONException;
进口org.json.JSONObject;进口android.content.ContentValues​​;
进口android.content.Context;
进口android.database.Cursor;
进口android.database.SQLException;
进口android.util.Log;/ **
 * @author rabbott
 *
 * /
公共类VenuesDataSource扩展appSQLiteHelper {    公共静态最后弦乐TABLE_NAME =场地;    //场地列
    公共静态最后弦乐KEY_NAME =名;
    公共静态最后弦乐KEY_DESCRIPTION =说明;
    公共静态最后弦乐KEY_START_TIME =START_TIME;
    公共静态最后弦乐KEY_ADDRESS =地址;
    公共静态最后弦乐KEY_CITY =城市;
    公共静态最后弦乐KEY_STATE =状态;
    公共静态最后弦乐KEY_ZIP =postal_ code;
    公共静态最后弦乐KEY_LNG =LNG
    公共静态最后弦乐KEY_LAT =纬度;
    公共静态最后弦乐KEY_PHONE =手机;    公共静态字符串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
    };    公共静态最后弦乐CREATE_STATEMENT =CREATE TABLE IF NOT EXISTS+ TABLE_NAME +(
            +_id INTEGER PRIMARY KEY AUTOINCREMENT
            +事项标识INTEGER NOT NULL,
            +Name文本NOT NULL,
            +的说明文字,
            +START_TIME TEXT
            +地址文本NOT NULL,
            +城市文本NOT NULL,
            +状态TEXT NOT NULL,
            +postal_ code文本
            +纬度TEXT
            +LNG TEXT
            +电话的文字,
            +created_at TEXT);;    公共VenuesDataSource(上下文的背景下){
        超级(上下文);        Log.i(VenueDataSource,构造);
    }    //在本地创建新的联系人
    众长createVenue(整数venue_id,整数事项标识,字符串名称,描述字符串,字符串START_TIME,字符串的地址,字符串市,字符串州,字符串postal_ code,字符串纬度,液化天然气字符串,字符串电话,字符串created_at){
        ContentValues​​ initialValues​​ =新ContentValues​​();        initialValues​​.put(DatabaseConstants.KEY_ROWID,EVENT_ID);
        initialValues​​.put(DatabaseConstants.KEY_EVENT_ID,EVENT_ID);
        initialValues​​.put(KEY_NAME,名);
        initialValues​​.put(KEY_DESCRIPTION,说明);
        initialValues​​.put(KEY_START_TIME,START_TIME);
        initialValues​​.put(KEY_ADDRESS,地址);
        initialValues​​.put(KEY_CITY,市);
        initialValues​​.put(KEY_STATE,状态);
        initialValues​​.put(KEY_ZIP,postal_ code);
        initialValues​​.put(KEY_PHONE,电话);
        initialValues​​.put(KEY_LAT,LAT);
        initialValues​​.put(KEY_LNG,LNG);
        initialValues​​.put(DatabaseConstants.KEY_CREATED_AT,created_at);        返回getWritableDatabase()插入(TABLE_NAME,空,initialValues​​)。
    }    //从本地数据库场地
    公共光标getVenue(长ROWID)抛出的SQLException {
        。光标mCursor = getWritableDatabase()查询(真,TABLE_NAME,COLUMNS_VENUES,DatabaseConstants.KEY_ROWID +=+ ROWID,NULL,NULL,NULL,NULL,NULL);        如果(mCursor!= NULL){
            mCursor.moveToFirst();
        }        返回mCursor;
    }    //更新本地会场
    众长updateVenue(整数venue_id,整数事项标识,字符串名称,描述字符串,字符串START_TIME,字符串的地址,字符串市,字符串州,字符串postal_ code,字符串纬度,液化天然气字符串,字符串电话){
        ContentValues​​ initialValues​​ =新ContentValues​​();        initialValues​​.put(DatabaseConstants.KEY_EVENT_ID,EVENT_ID);
        initialValues​​.put(KEY_NAME,名);
        initialValues​​.put(KEY_DESCRIPTION,说明);
        initialValues​​.put(KEY_START_TIME,START_TIME);
        initialValues​​.put(KEY_ADDRESS,地址);
        initialValues​​.put(KEY_CITY,市);
        initialValues​​.put(KEY_STATE,状态);
        initialValues​​.put(KEY_ZIP,postal_ code);
        initialValues​​.put(KEY_PHONE,电话);
        initialValues​​.put(KEY_LAT,LAT);
        initialValues​​.put(KEY_LNG,LNG);        。返回getWritableDatabase()更新(TABLE_NAME,initialValues​​,_id =?,新的String [] {Long.toString(venue_id)});
    }    //删除本地会场
    公共布尔deleteVenue(长ROWID){
        返回(getWritableDatabase()删除(TABLE_NAME,DatabaseConstants.KEY_ROWID +=+ ROWID,NULL)方式> 0);
    }    //检索所有本地场馆
    公共光标getAllVenues(长事项标识){
        光标mCursor = getWritableDatabase()查询(真,TABLE_NAME,COLUMNS_VENUES,DatabaseConstants.KEY_EVENT_ID +=+事项标识,
                NULL,NULL,NULL,NULL,NULL);        返回mCursor;
    }    公共布尔venueExists(INT venue_id){
        光标mCursor = getWritableDatabase()查询(真,TABLE_NAME,COLUMNS_VENUES,DatabaseConstants.KEY_ROWID +=+ venue_id,
                    NULL,NULL,NULL,NULL,NULL);        如果(mCursor.getCount()== 0){
            mCursor.close();
            返回false;
        }其他{
            mCursor.close();
            返回true;
        }
    }    公共无效parseVenue(JSONObject的venueJson)抛出JSONException {
        布尔venue_exists = FALSE;        INT EVENT_ID,venue_id;
        串venue_name,venue_description,START_TIME,venue_address,venue_city,venue_state,venue_postal_ code,纬度,经度,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);
        纬度= venueJson.getString(KEY_LAT);
        LNG = venueJson.getString(KEY_LNG);
        created_at = venueJson.getString(DatabaseConstants.KEY_CREATED_AT);        //检查,看看是否这个场地已经存在
        venue_exists = this.venueExists(venue_id);        如果(venue_exists ==真){
            this.updateVenue(
                    venue_id,
                    EVENT_ID,
                    venue_name,
                    venue_description,
                    开始时间,
                    venue_address,
                    venue_city,
                    venue_state,
                    venue_postal_ code,
                    纬度,
                    液化天然气,
                    venue_phone);
        }其他{
            this.createVenue(
                    venue_id,
                    EVENT_ID,
                    venue_name,
                    venue_description,
                    开始时间,
                    venue_address,
                    venue_city,
                    venue_state,
                    venue_postal_ code,
                    纬度,
                    液化天然气,
                    venue_phone,
                    created_at);
        }
    }    公共无效parseVenues(JSONArray venuesArray)抛出JSONException {
        的JSONObject venueJson;        的for(int i = 0; I< venuesArray.length();我++){
            //通过每个迭代场地
            venueJson = venuesArray.getJSONObject(ⅰ);            this.parseVenue(venueJson);
        }
    }
}


解决方案

问题是,第一个参数在 initLoader 方式是一种唯一标识每个项目加载,全是我的被设置为相同的(0)值 - 它们改变到一个唯一的值固定的问题

I am using an Activity that extends SherlockFragmentActivity, that has 3 tabs. The 3 tabs are ListFragments that implement LoaderManager.LoaderCallbacks. The OnCreate method for the Activity loads the tabs like so

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 ListFragments

if (savedInstanceState != null) {
    bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}

The layout that I'm loading the tabs into is very simple:

<?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>

Each of the tabs have a class that is identical to this, just called something different:

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 onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        cursorAdapter.swapCursor(cursor);

        // the list should now be shown
        if (isResumed()) {
            setListShown(true);
        } else {
            setListShownNoAnimation(true);
        }
    }

    public void onLoaderReset(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());
        }

    }
}

which uses the SimpleCursorLoaded defined here:

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;
    }
}

The issue I'm having is that when I select say.. the second tab (third tab does the same) it attempts to load the cursor, but when it tried to populate the list_items, I get an error saying

E/AndroidRuntime(2055): java.lang.IllegalArgumentException: column 'GIVEN_VARIABLE' does not exist

After setting a few break points I have discovered that the cursor its attempting to use is the cursor from the first tab, which loaded fine on inflation, but apparently isn't getting closed, and is apparently trying to be used again even though I (think) am sending it a different curser from getAllVenues()

EDIT: This is the last place the stack trace sends me When I set some breakpoints I can see that the cursor being provided here, is the cursor from the first tab, not that of the Venue tab..

EDIT: VenuesDataSource code to show the getAllVenues method

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);
        }
    }
}

解决方案

The issue is that the first parameter of the initLoader method is a way to uniquely identify each item to be loaded, all of mine were set to the same (0) value -- changing them to a unique value fixed the issue.

这篇关于SherlockFragmentActivity多ListFragments和SQLite光标战斗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆