1

これはおそらく非常に奇妙ですが、Android で複数の CursorLoader を使用して複数のクエリを実行し、onLoadFinished() で、TextViews や ListViews などのビューをカーソルの結果に基づいてレイアウトに動的に追加しています。正確な結果が得られますが、AsyncTaskLoader (CursorLoader) を使用しているため、カーソルの結果が同時に入力されず、結果が正しい順序で追加されません。以前は静的レイアウトを使用してインデックスにビューを追加し、結果に基づいて view.setVisiblity(View.GONE) を実行しましたが、32 個のビューがあるため、多すぎて混乱しすぎました。さらに、AsyncTaskLoader の結果に基づいて、これらすべてのビューが消えたり上下に移動したりすることをユーザーが望んでいるとは思わないため、奇妙に思えました。大量のブール変数を使用せずに、ビューを正しい順序で取得するにはどうすればよいですか? LayoutInflater を調べましたが、インデックスも必要ですが、それが役立つかどうかはわかりません。私にとってのインデックスの問題は、カーソルローダー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 が実行される場合、スペースが不足しているため、静的な 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 を使用します。このアドバイスは必ずしも真実ですか?少し大ざっぱに聞こえます。

ちなみに、私は ContentProvider なしで CursorLoader の使用法で指定されたコンテンツ プロバイダーなしで 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()

また、バックグラウンドスレッドでクエリを実行し、特定の順序で終了させたい場合は、カーソルローダーの代わりにサービスを使用する方がよいことをオンラインのどこかで読みましたが、他の場所でそのアドバイスを聞いたり、クエリを実行する例を見たりしませんでしたサービスで。

おそらく、受信IntentServiceした順序でキューをたどることができるものについて読んだことがあります。Intentsしかし、問題が増えるだけなので、これがどのように役立つかわかりません。戻す必要があるデータホルダーとして使用し、作成できないCursorsビューを作成する必要がある場合(さまざまな通信方法で作成する必要があります。これは私の観点からは不要な作業です) )。IntentServiceActivity

于 2013-06-13T14:22:56.603 に答える