5

コンテンツ プロバイダーによってデータが管理される SQLiteDatabase があります。タブ付きレイアウトを使用しています。最初のタブにはデータベースに行を追加する機能があり、2 番目のタブにはデータベースのアイテムが表示されます。最初のタブからデータベースにアイテムを追加すると、別のタブに移動したときに変更が反映されるはずです。

データはデータベースに正しく追加されており、アプリを最初に開くと、現在のすべてのデータ (および以前のバージョンのアプリで追加された新しいデータ) が表示されます。ただし、データベースに新しいアイテムを追加しても、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/の直接のクローンであり、現時点ではデータベースの各行の名前列を表示するだけです。以前のエントリが表示されますが、私が言ったように更新されません。更新するために欠けている手順は何ですか?

4

3 に答える 3

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);
}
于 2012-10-23T07:06:53.117 に答える
3

ビューページャーを使用してフラグメントで同様の問題が発生しました。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 を正しく呼び出していると仮定すると、これで問題が解決したようです (ただし、そうであるように見えます)。

これがあなたを助けることを願っています!

于 2012-10-25T23:00:24.620 に答える
-1

エラーはここにあると思います:

Uri newUri = ContentUris.withAppendedId(CONTENT_URI, rowId);
getContext().getContentResolver().notifyChange(uri, null);
return newUri;

追加した要素のuri( newUri)を使用してnotifyChangeメソッドを呼び出す必要があります。

したがって、通知は次のようになります。

getContext().getContentResolver().notifyChange(newUri, null);
于 2012-10-22T20:45:23.233 に答える