我有一个SQLiteDatabase,其数据由Content Provider管理。我正在使用标签式布局。第一个选项卡具有向数据库添加行的功能,而第二个选项卡显示数据库中的项目。当我从第一个选项卡向数据库添加项目时,当我移动到另一个选项卡时,应该会反映出来。
正确地将数据添加到数据库中,并且在首次打开应用程序时,将显示所有当前数据(以及在应用程序的先前版本中添加的任何新内容)。但是,向数据库中添加新项目不会反映在ListFragment中。
@Override
public void onClick(View v) {
if(v == addSale) {
Item item = new Item(rn(), null, 100);
data.add(item);
total += item.getAmount();
} else if(v == save) {
for(Item i: data) {
ContentValues cv = new ContentValues();
cv.put(DatabaseProvider.COLUMN_COST, i.getAmount());
cv.put(DatabaseProvider.COLUMN_ITEM, i.getItem());
cv.put(DatabaseProvider.COLUMN_PERSON, i.getPerson());
this.getActivity().getContentResolver().insert(DatabaseProvider.CONTENT_URI, cv);
}
total = 0;
data.clear();
} else if(v == clear) {
data.clear();
total = 0;
}
items.notifyDataSetChanged();
totalView.setText(Item.format(total));
}
以下是我将这些项目添加到数据库的具体位置:
ContentValues cv = new ContentValues();
cv.put(DatabaseProvider.COLUMN_COST, i.getAmount());
cv.put(DatabaseProvider.COLUMN_ITEM, i.getItem());
cv.put(DatabaseProvider.COLUMN_PERSON, i.getPerson());
this.getActivity().getContentResolver().insert(DatabaseProvider.CONTENT_URI, cv);
正如我之前所说,项目正确地放入数据库,所以我有理由相信这是正确的。
这是我的DatabaseProvider的插入方法
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
if (sUriMatcher.match(uri) != TABLE) {
throw new IllegalArgumentException("Invalid URI: " + uri);
}
if (initialValues == null) {
initialValues = new ContentValues();
}
SQLiteDatabase db = dbHelper.getWritableDatabase();
long rowId = db.insert(TABLE_SALES, COLUMN_COST, initialValues);
if (rowId > 0) {
Uri newUri = ContentUris.withAppendedId(CONTENT_URI, rowId);
getContext().getContentResolver().notifyChange(uri, null);
return newUri;
}
throw new SQLException("Failed to insert row into: " + uri);
}
从各种教程和其他SO问题看来,似乎
getContext().getContentResolver().notifyChange(uri, null);
是让它更新的关键,它就在那里,并被调用。但没有任何更新。
最后,我的列表片段显示所有数据。
package org.worldsproject.android.barcode;
import org.worldsproject.android.barcode.database.DatabaseProvider;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import com.actionbarsherlock.app.SherlockListFragment;
public class RunningTotal extends SherlockListFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
public static final String TAG = "Running Total";
public static final int RUNNING_TOTAL_ID = 1;
private SimpleCursorAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] uiBindFrom = { DatabaseProvider.COLUMN_PERSON };
int[] uiBindTo = { R.id.titled };
adapter = new SimpleCursorAdapter(
getActivity().getApplicationContext(), R.layout.list_title,
null, uiBindFrom, uiBindTo,
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
setListAdapter(adapter);
getLoaderManager().initLoader(RUNNING_TOTAL_ID, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
String[] projection = { DatabaseProvider.COLUMN_ID,
DatabaseProvider.COLUMN_PERSON};
return new CursorLoader(getActivity(), DatabaseProvider.CONTENT_URI,
projection, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
// TODO Auto-generated method stub
adapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> arg0) {
// TODO Auto-generated method stub
adapter.swapCursor(null);
}
}
它几乎是http://mobile.tutsplus.com/tutorials/android/android-sdk_loading-data_cursorloader/的直接克隆,目前只显示数据库中每行的名称列。它显示了以前的条目,但正如我所说,不会更新。我错过了什么步骤让它更新?
答案 0 :(得分:13)
我认为你的
getContext().getContentResolver().notifyChange(uri, null);
可能没问题。
我无法看到您的DatabaseProvider的查询函数,但是您是否记得为查询函数中返回的光标设置notificationUri?
在DatabaseProvider的query()函数中,您应该为游标设置通知Uri,否则即使您执行notifyChange(),游标也不会收到通知:
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
// blah blah
cursor.setNotificationUri(getContext().getContentResolver(), uri);
}
答案 1 :(得分:3)
我使用视图寻呼机与Fragment有类似的问题。我意识到我没有注册ContentObserver,所以我所做的只是将此代码添加到onResume()
getActivity().getContentResolver().registerContentObserver(sUri, true, myObserver);
并将myObserver声明为成员变量:
new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
getActivity().getSupportLoaderManager().restartLoader(); // With appropriate loader args here
}
});
确保取消注册在onPause();
中这似乎解决了我的问题,假设ContentProvider正确调用notifyChange(看起来你好像是。)
希望这会帮助你!
答案 2 :(得分:-1)
我认为错误就在这里:
Uri newUri = ContentUris.withAppendedId(CONTENT_URI, rowId);
getContext().getContentResolver().notifyChange(uri, null);
return newUri;
您应该使用刚刚添加的元素的uri调用 notifyChange 方法,这是newUri。
因此通知变为:
getContext().getContentResolver().notifyChange(newUri, null);