这可能很奇怪,但我在Android中使用多个CursorLoaders来做多个查询,并在onLoadFinished()中,我正在根据光标结果动态地添加视图,如TextViews和ListViews到我的布局,如果光标不为空。我确实得到了准确的结果,但由于我使用的是AsyncTaskLoader (CursorLoader),因此光标结果不会同时进入,并且结果不会以正确的顺序添加。我以前使用过静态布局,并在索引中添加了视图,并根据结果添加了view. setvisibility (View.GONE),但它太多了,太令人困惑了,因为我有32个视图。另外,这看起来很奇怪,因为我不认为用户希望看到所有这些视图消失,并根据AsyncTaskLoader的结果上下移动。如何在不使用一堆布尔变量的情况下让视图按我想要的顺序排列?我研究了LayoutInflater,但它也需要索引,但我不确定这是否会对我有帮助。索引对我来说的问题是,在cursorloader ID 1:
view.addView(v, 1);
view.addView(v, 2);
可能不会被执行,直到ID为2的游标加载器完成:
view.addView(v, 3);
view.addView(v, 4);
如果cursorLoader ID 1没有得到执行,ID 2做,然后有缺失的空间,我必须做一个吨的view.setVisibility(View.GONE),如果我使用静态XML视图,不动态添加它们。
在代码中,我正在做这样的事情:
@Override
public void onLoadFinished(android.support.v4.content.Loader<Cursor> cursorLoader, Cursor cursor) {
switch (cursorLoader.getId())
{
case 0:
if (cursor != null && cursor.moveToFirst()) {
..
title = new TextView(this);
...
mainLinearLayout.addView(title, 1);
}
break;
case 1:
if (cursor != null && cursor.moveToFirst()) {
..
title2 = new TextView(this);
mainLinearLayout.addView(title2, 2);
break;
default:
...
}
}
我也在网上某处读到,如果你想在后台线程上做查询,并让它们以一定的顺序完成,最好使用服务而不是cursorloader,但我没有听到其他地方的建议,也没有看到任何在服务中做查询的例子。它们都使用CursorLoader。这个建议一定正确吗?听起来有点粗略。
顺便说一下,我使用的是没有内容提供程序的CursorLoader实现在CursorLoader使用中没有ContentProvider
我如何使视图在正确的顺序,我想在没有有一堆布尔变量?
你确实需要一些状态控制来使视图按顺序显示。我将把视图的构造/添加委托给一个控制类,该控制类将拥有创建正确视图所需的所有信息,并且无论加载器如何完成它们的工作。
public class ViewDispatcher {
public SparseArray<Status> mLoadStatuses = new SparseArray<Status>();
public SparseArray<Cursor> mDataCursors = new SparseArray<Cursor>();
// you'll call this method for each of the loaders, in the order they should be. The ids should be incremental
public void registerLoader(int loaderId) {
mLoadStatuses.put(loaderId, Status.INITIAL);
}
// called when one of the loaders finishes its job
public void onLoadComplete(int loaderId, Cursor data) {
mDataCursors.put(loaderId, data);
boolean current = true;
mLoadStatuses.put(loaderId, Status.LOADED);
if (loaderId == firstLoaderId) {
// the first loader it's done and we should start the view creation right away
buildView(loaderId, mainLayout, true);
mLoadStatuses.put(loaderId, data, Status.FULLY_BUILT);
} else {
// implement a priority system, a view construction will be triggered ONLY
// if the previous loader has finished loading data and its view is in place
// I'm assuming that the Loaders have consecutive ids
if (mLoadStatuses.get(loaderId - 1) != null && mLoadStatuses.get(loaderId - 1) == Status.FULLY_BUILT) {
buildView(loaderId, data, mainLayout, true);
mLoadStatuses.put(loaderId, Status.FULLY_BUILT);
} else {
current = false;
}
}
// we'll also need to implement a buddy system. When a loader is done loading and its view
// is created we must check to see if we don't have other loaders after this current one that have finished loading
// but couldn't construct their view because this current loader didn't finished at that moment
// get the next loader
int next = loaderId + 1;
while(current && next < totalNumberOfLoaders && mLoadStatuses.get(next) == Status.LOADED) {
// continue to build views
buildView(next, mDataCursors.get(loaderId), mainLayout, true);
mLoadStatuses.put(next, Status.FULLY_BUILT);
next++;
}
}
// this will build the appropriate view, and optionally attach it
public void buildView(int loaderId, Cursor data, view mainLayout, boolean attach) {
// build the view for this specific Loader
}
}
public enum Status {
INITIAL, LOADED, FULLY_BUILT
}
我希望我没有错过一些明显的东西,因为我没有写任何测试。要使用它,您将首先按照您需要的顺序为所有加载器调用registerLoader()
方法,并在LoaderCallbacks
的onLoadComplete()
回调中调用ViewDispatcher.onLoadComplete()
。
我还在网上读到,最好使用服务而不是cursorloader如果你想在后台进行查询把它们按一定的顺序织好,但我没有听说过这个建议在其他地方或看到任何例子做查询服务。
你可能已经读过IntentService
,它可以通过Intents
接收的顺序来跟随队列。但是,我看不出这对你有什么帮助,因为它只会增加问题。首先,您使用Cursors
作为您需要传递的数据持有人,并且您需要创建IntentService
无法执行的视图(它需要使Activity
通过各种通信方式创建它们,从我的角度来看,这是不必要的工作)。