草庐IT

Android CursorLoader 不响应 ContentProvider 通知

coder 2023-12-15 原文

我正在更新一个 Android 2.2 应用程序以使用 CursorLoader(使用 v4 兼容性库),我正在焦头烂额地试图理解为什么当内容提供者时 onLoadFinished 方法没有被调用通知与 CursorLoader 查询关联的内容发生变化。

CursorLoader 正在查询客户内容提供者。我的提供商在其查询方法中设置通知 URI:

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

并通知其插入/更新/删除方法的变化:

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

我已经检查过这两种情况下的 URI 是否相同。以前我使用的是具有相同内容提供者的 ManagedQuery,查询的内容更新得很好,这让我认为内容提供者可能没问题。

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

最佳答案

我终于弄清楚了这件事,而且,就像往常一样,这对我来说是一个愚蠢的错误。我在我的 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);
        }
    }

}

关于Android CursorLoader 不响应 ContentProvider 通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8919198/

有关Android CursorLoader 不响应 ContentProvider 通知的更多相关文章

  1. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  2. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  3. ruby-on-rails - 如何在发布新的 Ruby 或 Rails 版本时收到通知? - 2

    有人知道在发布新版本的Ruby和Rails时收到电子邮件的方法吗?他们有邮件列表,RubyonRails有一个推特,但我不想听到那些随之而来的喧嚣,我只想知道什么时候发布新版本,尤其是那些有安全修复的版本。 最佳答案 从therailsblog获取提要.http://weblog.rubyonrails.org/feed/atom.xml 关于ruby-on-rails-如何在发布新的Ruby或Rails版本时收到通知?,我们在StackOverflow上找到一个类似的问题:

  4. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  5. ruby - 从 Ruby 连接到适用于 Windows Phone 8 的 Microsoft 推送通知服务 - 2

    我们正在开发一个需要推送通知的WP8应用程序。为了测试它,我们使用CURL命令行运行推送通知POST请求,确保它实际连接,使用客户端SSL证书进行身份验证并发送正确的数据。我们确实知道,当我们收到对设备的推送时,这项工作是有效的。这是我们一直用于测试目的的CURL命令:curl--certclient_cert.pem-v-H"Content-Type:text/xml"-H"X-WindowsPhone-Target:Toast"-H"X-NotificationClass:2"-XPOST-d"MytitleMysubtitle"https://db3.notify.live.ne

  6. ruby - 是否可以在 Unicorn master 完成重启时发送通知? - 2

    我在nginx+unicorn后面运行一系列Rails/Sinatra应用程序,零停机部署。我喜欢这个设置,但Unicorn需要一段时间才能完成重新启动,所以我想在完成时发送某种通知。我能在Unicorn文档中找到的唯一回调与workerfork相关,但我认为这些回调对此不起作用。这是我从赏金中寻找的东西:老unicorn主人启动新主人,然后新主人开始它的worker,然后旧主人停止它的worker并让新主人接管。我想在交接完成后执行一些ruby​​代码。理想情况下,我不想为此实现任何复杂的流程监控。如果这是唯一的方法,那就这样吧。但在走那条路之前,我正在寻找更简单的选择。

  7. ruby-on-rails - Rails 在记录 200 OK 后在做什么? (调试响应时间慢) - 2

    我试图在我的RubyonRails应用程序中调试一个极其缓慢的请求调用。我已设法根据自己的喜好优化Controller方法,Rails的日志告诉我它已在XX毫秒内完成操作(Completed200OKin5049ms(Views:34.9ms|ActiveRecord:76.3ms)).但是,在加载页面时,在浏览器中实际呈现任何内容之前打印此消息很长;最多约15秒的等待时间。Rackmini-profiler证实了这一点,告诉我GET操作(不计算完成Controller操作所花费的时间)花费了14秒左右。(分析器还确认Controller操作的执行时间约为5秒)。我可以接受Contro

  8. ruby - 带有 header 的 Sinatra 流式响应 - 2

    我想通过Sinatra应用程序代理远程文件。这需要将带有header的HTTP响应从远程源流式传输回客户端,但我不知道如何在Net::HTTP#提供的block内使用流式API时设置响应header获取响应。例如,这不会设置响应头:get'/file'dostreamdo|out|uri=URI("http://manuals.info.apple.com/en/ipad_user_guide.pdf")Net::HTTP.get_response(uri)do|file|headers'Content-Type'=>file.header['Content-Type']file.re

  9. ruby - Net::HTTP 对 HTTPS 请求的响应极其缓慢 - 2

    出于某种原因,在我的开发机器上,我对通过Net::HTTP执行的HTTPS请求的响应非常非常慢。我试过RestClient和HTTParty,它们都有同样的问题。它似乎是凭空冒出来的。我已毫无问题地提出这些请求数百次,但今天它们的速度慢得令人难以忍受。pry(main)>putsTime.now;HTTParty.get('https://api.easypost.com/v2/addresses');putsTime.now;2015-04-2908:07:08-05002015-04-2908:09:39-0500如您所见,响应耗时2.5分钟。不仅仅是这个EasyPostAPIUR

  10. ruby - 使用 Ruby 将 HTTP GET 的响应主体流式传输到 HTTP POST - 2

    我正在尝试下载一个大文件,然后使用Ruby将该文件发布到REST端点。该文件可能非常大,即超过可以存储在内存中甚至磁盘上的临时文件中的容量。我一直在用Net::HTTP尝试这个,但我愿意接受任何其他库(rest-client等)的解决方案,只要他们做我想做的事情。这是我尝试过的:require'net/http'source_uri=URI("https://example.org/very_large_file")source_request=Net::HTTP::Get.new(source_uri)source_http=Net::HTTP.start(source_uri.ho

随机推荐