为Android Loaders实现侦听数据更改

时间:2017-04-06 08:14:21

标签: android loader

我在下面的代码中编写了简单的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();
}

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

1 个答案:

答案 0 :(得分:0)

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

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

我们需要定义我们的自定义加载器,它扩展了AsyncTaskLoader并实现了它的所有抽象方法。与CursorLoader不同,我们的自定义加载器可能会也可能不会使用内容提供程序,并且当此加载器被实例化时,它的构造函数可能不会调用ContentResolver.query()。所以我们使用广播接收器来达到目的。 我们需要在抽象AsyncTaskLoader类的OnStartLoading()方法中实例化BroadCastReceiver或ContentObserver。 应该定义此BroadCast接收器以从内容提供者或任何系统事件(如新安装的应用程序)接收数据更改广播,并且必须调用loader的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);

使用getContentResolver().unregisterContentObserver(mObserver);

onPause()上取消注册