Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/189.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/205.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android CursorLoader未响应ContentProvider通知_Android_Android Contentprovider_Android Cursorloader - Fatal编程技术网

Android CursorLoader未响应ContentProvider通知

Android CursorLoader未响应ContentProvider通知,android,android-contentprovider,android-cursorloader,Android,Android Contentprovider,Android Cursorloader,我正在更新一个Android 2.2应用程序以使用CursorLoader(使用v4兼容库),我正在绞尽脑汁试图理解为什么当内容提供商通知与CursorLoader查询相关的内容发生更改时,不会调用onLoadFinished方法 游标加载程序正在查询客户内容提供程序。My provider在其查询方法中设置通知URI: cursor.setNotificationUri(getContext().getContentResolver(), uri); 并通知其插入/更新/删除方法的更改: g

我正在更新一个Android 2.2应用程序以使用CursorLoader(使用v4兼容库),我正在绞尽脑汁试图理解为什么当内容提供商通知与CursorLoader查询相关的内容发生更改时,不会调用
onLoadFinished
方法

游标加载程序正在查询客户内容提供程序。My provider在其查询方法中设置通知URI:

cursor.setNotificationUri(getContext().getContentResolver(), uri);
并通知其插入/更新/删除方法的更改:

getContext().getContentResolver().notifyChange(uri, null);
我检查了两种情况下的URI是否相同。以前,我对同一个内容提供者使用ManagedQuery,查询的内容更新得很好,这让我觉得内容提供者可能还可以


我看过这个示例,有趣的是,当我在NexusOne上运行它时,我没有看到它反映了我对联系人姓名所做的更改(在示例应用程序和联系人应用程序之间切换)。应该吗?如果是这样,是否存在我不知道的潜在问题?

也许您应该使用应用程序上下文:

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

我终于找到了问题的症结所在,就像往常一样,我犯了一个愚蠢的错误。我在onLoadFinished()方法中调用cursor.close()——我使用返回的游标创建ArrayAdapter(我需要手动在列表顶部插入一个项),而游标close是迁移到使用CursorLoader之前使用ManagedQuery的遗留问题

在查找这个的过程中,我创建了一个简单的测试类来显示书签列表并添加一个随机书签(使用选项菜单)。这是正常工作的,即在添加项后调用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);
        }
    }

}
package.com.test;
导入android.content.ContentValues;
导入android.database.Cursor;
导入android.os.Bundle;
导入android.provider.Browser;
导入android.support.v4.app.FragmentActivity;
导入android.support.v4.app.FragmentManager;
导入android.support.v4.app.ListFragment;
导入android.support.v4.app.LoaderManager;
导入android.support.v4.content.CursorLoader;
导入android.support.v4.content.Loader;
导入android.support.v4.view.MenuItemCompat;
导入android.support.v4.widget.SimpleCursorAdapter;
导入android.util.Log;
导入android.view.Menu;
导入android.view.MenuInflater;
导入android.view.MenuItem;
公共类CursorLoaderTestActivity扩展了FragmentActivity
{
私有静态最终字符串标记=CursorLoaderTestActivity.class.getSimpleName();
@凌驾
创建时受保护的void(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
FragmentManager fm=getSupportFragmentManager();
//创建列表片段并将其添加为我们的唯一内容。
if(fm.findFragmentById(android.R.id.content)==null)
{
CursorLoaderListFragment列表=新的CursorLoaderListFragment();
fm.beginTransaction().add(android.R.id.content,list.commit();
}
}
公共静态类CursorLoaderListFragment扩展ListFragment实现LoaderManager.LoaderCallbacks
{
//这是用于显示列表数据的适配器。
简单的适应;
//如果非空,则这是用户提供的当前筛选器。
串滤波器;
@在ActivityCreated(Bundle savedInstanceState)上重写公共void
{
super.onActivityCreated(savedInstanceState);
//如果没有数据,则提供一些文本以显示。在实际
//应用程序这将来自一个资源。
setEmptyText(“无数据”);
//我们有一个菜单项显示在行动栏。
设置选项菜单(真);
//创建一个空适配器,用于显示加载的数据。
mAdapter=new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_1,null,
新字符串[]{Browser.bookmark columns.TITLE},
新的int[]{android.R.id.text1},0);
setListAdapter(mAdapter);
//从进度指示器开始。
SetListShowed(假);
//准备加载程序。或者重新连接现有加载程序,
//或者开始一个新的。
getLoaderManager().initLoader(0,null,this);
}
//@凌驾
创建选项菜单(菜单菜单,菜单充气机)
{
//放置一个用于搜索的操作栏项。
MenuItem item=menu.add(“添加项”);
//设置图标(android.R.drawable.ic\u菜单\u搜索);
menuitecompat.setShowAsAction(item,menuiteCompat.SHOW_AS_ACTION_u0;始终);
}
@凌驾
公共布尔值onOptionsItemSelected(菜单项项)
{
ContentValues cv=新的ContentValues();
cv.put(Browser.BookmarkColumns.TITLE,“!AA”+System.currentTimeMillis());
cv.put(Browser.BookmarkColumns.URL,“http://test/");
cv.put(Browser.BOOKMARK columns.BOOKMARK,1);
getActivity().getContentResolver().insert(Browser.BOOKMARKS\u URI,cv);
返回true;
}
//要查询的列
静态最终字符串[]投影=新字符串[]{Browser.BookmarkColumns.TITLE};
公共加载器onCreateLoader(int-id,Bundle-args)
{
Log.i(标记“onCreateLoader”);
返回新的游标装入器(getActivity(),Browser.BOOKMARKS\u URI,
投影,空,空,
Browser.bookmark columns.TITLE+“ASC”);
}
public void onLoadFinished(加载器、光标数据)
{
Log.i(标记“onLoadFinished”);
//在中交换新光标。(框架将负责关闭
//我们返回后,将返回旧光标。)
mAdapter.swapCursor(数据);
//名单现在应该是