1

这可能很奇怪,但我在 Android 中使用多个 CursorLoaders 来执行多个查询,并且在 onLoadFinished() 中,我根据游标结果动态地将 TextViews 和 ListViews 等视图添加到我的布局中,例如游标不为空。我确实得到了准确的结果,但是由于我使用的是 AsyncTaskLoader (CursorLoader),因此光标结果不会同时出现,并且结果不会以正确的顺序添加。我以前使用静态布局并在索引处添加视图,并根据结果执行 view.setVisiblity(View.GONE) ,但这实在是太多太混乱了,因为我有 32 个视图。另外,这似乎很奇怪,因为我认为用户不希望看到所有这些视图都消失并根据 AsyncTaskLoader 结果上下移动。如何在没有一堆布尔变量的情况下以我想要的正确顺序获取视图?我查看了 LayoutInflater 但这也需要索引,但我不确定这会对我有帮助。对我来说,索引的问题是在 cursorloader ID 1 中:

    view.addView(v, 1);
    view.addView(v, 2);

直到 ID 为 2 的 cursorloader 完成以下操作才能执行:

    view.addView(v, 3);
    view.addView(v, 4);

如果 cursorLoader ID 1 没有被执行而 ID 2 被执行,那么就会缺少空间,如果我使用静态 XML 视图并且不动态添加它们,我必须做大量的 view.setVisibility(View.GONE) 。

在代码中,我目前正在做这样的事情:

     @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。这个建议一定是真的吗?听起来有点粗略。

顺便说一句,我正在使用没有 ContentProvider 的CursorLoader 使用没有 ContentProvider的 CursorLoader 实现

4

1 回答 1

0

如何在没有一堆布尔变量的情况下以我想要的正确顺序获取视图?

您确实需要某种状态控制以使视图按顺序显示。我会将视图构造/添加委托给一个控件类,该控件类将具有制作正确视图所需的所有信息,并且无论加载程序如何完成工作,都以正确的顺序进行。

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()按照您需要它们的顺序并在 call 的onLoadComplete()回调中LoaderCallbacks调用所有加载器的方法ViewDispatcher.onLoadComplete()

我还在网上某处读到,如果您想在后台线程上进行查询并让它们按特定顺序完成,最好使用服务而不是 cursorloader,但我在其他任何地方都没有听到过这个建议,也没有看到任何查询示例在服务中。

您可能已经阅读过IntentService哪些可以按照队列Intents接收到的顺序来跟随队列。但是,我看不出这会对您有什么帮助,因为它只会增加问题。对于您Cursors用作需要传回的数据持有者并且您需要创建IntentService不能做的视图的人(它需要Activity通过各种通信方式创建它们,从我的角度来看,这是不必要的工作)。

于 2013-06-13T14:22:56.603 回答