【问题标题】:Implementing Listening data changes for Android Loaders为 Android 加载器实现监听数据更改
【发布时间】:2017-04-06 08:14:21
【问题描述】:

我编写了简单的Loader 如下代码,我希望将数据添加到List,并且我的 RecyclerView 适配器通过使用notifyDataSetChanged() 刷新列表知道这一点

我的加载器类:

public class StringLoader extends AsyncTaskLoader<List<RobotViewModel>> {
    private        List<RobotViewModel> cache;
    private static List<RobotViewModel> model;

    public StringLoader(Context context) {
        super(context);
    }

    @Override
    protected void onStartLoading() {
        if (cache == null) {
            forceLoad();
        } else {
            super.deliverResult(cache);
        }
    }

    @Override
    public List<RobotViewModel> loadInBackground() {
        Log.e("LOAD......... ", "new");
        model = new ArrayList<>();
        return model;
    }

    public void addCommand() {
        RobotViewModel temp = new RobotViewModel();
        temp.setMessage("hello");
        temp.setMessageType(SV.RobotMessageType.SENT_BY_ROBOT.ordinal());
        model.add(temp);

        forceLoad();
    }

    @Override
    public void deliverResult(List<RobotViewModel> data) {
        cache = data;
        super.deliverResult(data);
    }
}

我使用活动中的addCommand() 方法:

public void clickOnSendCommand() {
    loader.addCommand();
    adapter.notifyDataSetChanged();
}

我的活动和实现适配器和加载器:

public class ActivityRegister extends BaseActivities {

    private RobotMessagesAdapter adapter;
    private StringLoader         loader;

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

        ...

        ActivityRegisterPresenter presenter = new ActivityRegisterPresenter(this);
        ActivityRegisterViewModel viewModel = new ActivityRegisterViewModel();
        binding.setViewModel(viewModel);
        binding.setPresenter(presenter);

        List<RobotViewModel> model = new ArrayList<>();
        adapter = new RobotMessagesAdapter(this, model);
        binding.registerRobot.setAdapter(adapter);

        loader = (StringLoader) getSupportLoaderManager().initLoader(R.id.string_loader_id, null, loaderCallbacks);
    }

    private LoaderManager.LoaderCallbacks<List<RobotViewModel>> loaderCallbacks = new LoaderManager.LoaderCallbacks<List<RobotViewModel>>() {
        @Override
        public Loader<List<RobotViewModel>> onCreateLoader(int id, Bundle args) {
            return new StringLoader(getApplicationContext());
        }

        @Override
        public void onLoadFinished(Loader<List<RobotViewModel>> loader, List<RobotViewModel> data) {
            adapter.setData(data);
        }

        @Override
        public void onLoaderReset(Loader<List<RobotViewModel>> loader) {
            adapter.setData(Collections.<RobotViewModel>emptyList());
        }
    };

setData() 适配器上的方法:

public void setData(List<RobotViewModel> data) {
    list.clear();
    list.addAll(data);
    notifyDataSetChanged();
}

将项目添加到列表通常没有任何问题,并且工作正常,但我想向其中添加项目并刷新适配器

【问题讨论】:

  • @pskink 我不懂我的意思
  • @pskink 在这个源代码中mObserver 可以通过cursor.registerContentObserver(mObserver); 注册我没有Cursor 而我的AsyncTaskLoaderList&lt;RobotViewModel&gt; 不是Cursor,我该如何使用registerContentObserver ?
  • @pskink 我正在尝试在后台从数据库加载数据并在设备方向缓存数据
  • @pskink 好的,你能链接我如何在改变方向设备上缓存数据吗?我找不到这个功能
  • 您是否使用过saveInstancestate() 方法来存储有关原始更改的数据。

标签: android loader


【解决方案1】:

对于自定义加载器,您必须创建自己的观察者,每当表格发生变化时,您将继续观察表格的 URI,然后您将在观察者或加载器上获得回调,您可以更新您的视图。

您可以使用光标以外的其他对象来指向加载的数据(如列表等)。在这种情况下,我们将无权通过光标通知 ContentResolver。应用程序也可能没有内容提供程序来跟踪 URI 更改。在这种情况下,我们使用 BroadcastReceiver 或显式 ContentObserver 来实现自动视图更新。如下:

我们需要定义我们的自定义加载器,它扩展了 AsyncTaskLoader 并实现了它的所有抽象方法。与 CursorLoader 不同的是,我们的自定义加载器可能使用也可能不使用内容提供程序,并且当此加载器启动时,它的构造函数可能不会调用 ContentResolver.query()。所以我们使用广播接收器来达到目的。 我们需要在抽象 AsyncTaskLoader 类的 OnStartLoading() 方法中实例化一个 BroadCastReceiver 或 ContentObserver。 这个广播接收器应该被定义为从内容提供者或任何系统事件(如安装的新应用程序)接收数据更改广播,并且它必须调用加载程序的 onContentChanged() 方法,以通知加载程序有关数据更改。 Loader 自动完成剩下的工作来加载更新的数据并调用 onLoadFinished() 来更新视图。

更多详情请参考:http://developer.android.com/reference/android/content/AsyncTaskLoader.html http://www.androiddesignpatterns.com/2012/08/implementing-loaders.html

示例代码

将此代码添加到您的活动中

private final ContentObserver mObserver = new ThrottledContentObserver( 
new ThrottledContentObserver.Callbacks() {
                 @Override
               public void onThrottledContentObserverFired() {
                    getSupportLoaderManager().restartLoader(LOADER_ID, null, MainActivity.this);
               }
            });

并使用
onResume() 上注册以下变量 getContentResolver().registerContentObserver(CONTENT_URI, true, mObserver);

并在 onPause() 上使用 getContentResolver().unregisterContentObserver(mObserver); 取消注册

【讨论】:

  • 你能更新我的代码吗?如果我很难理解它
  • 请让我检查一下
猜你喜欢
  • 2015-01-30
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多