5

CursorLoader (v4 互換性ライブラリを使用) を使用するように Android 2.2 アプリケーションを更新していますonLoadFinished。コンテンツ プロバイダーが CursorLoader クエリに関連付けられたコンテンツの変更を通知したときにメソッドが呼び出されない理由を理解しようと、頭を悩ませています。 .

CursorLoader は、顧客のコンテンツ プロバイダーにクエリを実行しています。私のプロバイダーは、クエリ メソッドで通知 URI を設定します。

cursor.setNotificationUri(getContext().getContentResolver(), uri);

挿入/更新/削除メソッドの変更を通知します。

getContext().getContentResolver().notifyChange(uri, null);

どちらの場合も URI が同一であることを確認しました。以前は、同じコンテンツ プロバイダーで ManagedQuery を使用していましたが、クエリを実行したコンテンツは適切に更新されていたため、コンテンツ プロバイダーはおそらく問題ないと思います。

LoaderCursorSupportの例を見てきましたが、興味深いことに、Nexus One で実行すると、連絡先の名前に加えた変更 (サンプル アプリと連絡先アプリの切り替え) が反映されていません。それはすべきですか?もしそうなら、私が気付いていない根本的な問題はありますか?

4

2 に答える 2

4

私はついにこれの真相にたどり着きましたが、いつものように、それは私の側のばかげた間違いでした。私は onLoadFinished() メソッドで cursor.close() を呼び出していました - 返されたカーソルを使用して ArrayAdapter を作成し (リストの一番上に項目を手動で挿入する必要があります)、カーソルのクローズは ManagedQuery を使用した残り物でしたCursorLoader を使用するように移行する前に。

これを見つける過程で、ブックマークのリストを表示し、(オプション メニューを使用して) ランダムなブックマークを追加する簡単なテスト クラスを作成しました。これは正常に機能しました。つまり、アイテムが追加された後に onLoadFinished() が呼び出されます。他の人に役立つ場合のコードは次のとおりです。

package com.test;

import android.content.ContentValues;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.Browser;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SimpleCursorAdapter;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

public class CursorLoaderTestActivity extends FragmentActivity 
{
    private static final String TAG = CursorLoaderTestActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);

        FragmentManager fm = getSupportFragmentManager();

        // Create the list fragment and add it as our sole content.
        if (fm.findFragmentById(android.R.id.content) == null) 
        {
            CursorLoaderListFragment list = new CursorLoaderListFragment();
            fm.beginTransaction().add(android.R.id.content, list).commit();
        }
    }


    public static class CursorLoaderListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> 
    {

        // This is the Adapter being used to display the list's data.
        SimpleCursorAdapter mAdapter;

        // If non-null, this is the current filter the user has provided.
        String mCurFilter;

        @Override public void onActivityCreated(Bundle savedInstanceState) 
        {
            super.onActivityCreated(savedInstanceState);

            // Give some text to display if there is no data.  In a real
            // application this would come from a resource.
            setEmptyText("No data");

            // We have a menu item to show in action bar.
            setHasOptionsMenu(true);

            // Create an empty adapter we will use to display the loaded data.
            mAdapter = new SimpleCursorAdapter(getActivity(),
                    android.R.layout.simple_list_item_1, null,
                    new String[] { Browser.BookmarkColumns.TITLE },
                    new int[] { android.R.id.text1}, 0);

            setListAdapter(mAdapter);

            // Start out with a progress indicator.
            setListShown(false);

            // Prepare the loader.  Either re-connect with an existing one,
            // or start a new one.
            getLoaderManager().initLoader(0, null, this);
        }

        //@Override 
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) 
        {
            // Place an action bar item for searching.
            MenuItem item = menu.add("Add Item");
            //item.setIcon(android.R.drawable.ic_menu_search);
            MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
        }

        @Override
        public boolean onOptionsItemSelected (MenuItem item)
        {
            ContentValues cv=new ContentValues();
            cv.put(Browser.BookmarkColumns.TITLE, "!AA " + System.currentTimeMillis());
            cv.put(Browser.BookmarkColumns.URL, "http://test/");
            cv.put(Browser.BookmarkColumns.BOOKMARK, 1);
            getActivity().getContentResolver().insert(Browser.BOOKMARKS_URI, cv);
            return true;
        }

       //columns to query
        static final String[] PROJECTION = new String[] { Browser.BookmarkColumns.TITLE };


        public Loader<Cursor> onCreateLoader(int id, Bundle args) 
        {
            Log.i(TAG, "onCreateLoader");

            return new CursorLoader(getActivity(), Browser.BOOKMARKS_URI,
                    PROJECTION, null, null,
                    Browser.BookmarkColumns.TITLE + " ASC");
        }

        public void onLoadFinished(Loader<Cursor> loader, Cursor data) 
        {
            Log.i(TAG, "onLoadFinished");

            // Swap the new cursor in.  (The framework will take care of closing the
            // old cursor once we return.)
            mAdapter.swapCursor(data);

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

        public void onLoaderReset(Loader<Cursor> loader) 
        {
            // This is called when the last Cursor provided to onLoadFinished()
            // above is about to be closed.  We need to make sure we are no
            // longer using it.
            mAdapter.swapCursor(null);
        }
    }

}
于 2012-01-19T11:31:08.933 に答える
-1

たぶん、アプリケーションコンテキストを使用する必要があります。

getContext().getApplicationContext().getContentResolver().notifyChange(uri, null);
于 2012-01-18T23:56:18.400 に答える