3

DBFlow (SQLite) バックエンドから供給された RecyclerView リストを表示しようとしています。リスト内の各項目は、一度選択すると詳細アクティビティ ビューに遷移する項目を表します。他の CursorLoader と同様に、ビューをサポートする Loader で変更が発生するたびに、レイアウトが自動的に更新されることを期待しています。

これはMarshmallowでテストする場合には当てはまりますが、 LollipopJelly Bean (4.3)の両方では失敗します。失敗した場合、デバッガーでonBindViewHolder()がアイテムごとに 1 回呼び出されるのを確認しても (適切なデータがカーソルに到着します) 、単一のアイテムがリストに表示されます。

以下は、私の意見に関係する主な要素です。意図的にコードを簡略化しました。必要に応じて詳細をリクエストしてください。


リストを表示するアクティビティの onResume() オーバーライド:

@Override
protected void onResume() {
    super.onResume();

    getSupportLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks<Cursor>() {
        @Override
        public Loader<Cursor> onCreateLoader(int arg0, Bundle cursor) {
            return BackendManager.getListCursorLoader(mContext);
        }

        @Override
        public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
            int numItemsRetrieved = cursor.getCount();
            if ((numItemsRetrieved == 1) {
                Optional<Item> selectedItemOpt = BackendManager.getSingleItem();

                if (selectedItemOpt.isPresent()) {
                    Item selectedItem = selectedItemOpt.get();

                    Intent t = new Intent(mContext, ItemDetailActivity.class);
                    Bundle b = new Bundle();
                    b.putSerializable("item", selectedItem);
                    it.putExtras(b);
                    startActivityForResult(it, SHOW_ITEM_DETAIL);
                }
            }

            ((ItemListRecyclerAdapter) mRecyclerListView.getAdapter()).swapCursor(cursor);
        }

        @Override
        public void onLoaderReset(Loader<Cursor> arg0) {
            ((ItemListRecyclerAdapter) mRecyclerListView.getAdapter()).swapCursor(null);
        }
    });
}

静的マネージャー内での CursorLoader の生成:

public static CursorLoader getListCursorLoader(Context ctx) {
    return new CursorLoader(
            ctx,                                            // Context
            Item.CONTENT_URI,                               // Uri
            null,                                           // Projection
            null,                                           // Selection
            null,                                           // selectionArgs
            null                                            // sortOrder
    );
}

カーソル用の RecyclerView アダプター。現在スカイフィッシュを使用しています:

public class ItemListRecyclerAdapter extends CursorRecyclerViewAdapter<ItemListRecyclerAdapter.ViewHolder> {

    private Context mContext;

    public ItemListRecyclerAdapter(Context context, Cursor cursor) {
        super(context, cursor);

        mContext = context;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView itemText;
        public ImageView itemImage;

        public ViewHolder(View view) {
            super(view);
            itemText = (TextView) view.findViewById(R.id.itemTitle);
            itemImage = (ImageView) view.findViewById(R.id.itemPicture);
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.activity_6_list_item, parent, false);
        ViewHolder vh = new ViewHolder(itemView);
        return vh;
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, Cursor cursor) {

        // Find fields to populate in inflated template
        String itemTextData = cursor.getString(cursor.getColumnIndex("itemText"));
        viewHolder.itemText.setText(itemTextData);
        // Force text fit
        AutofitHelper afh = AutofitHelper.create(viewHolder.itemText);
        afh.setMaxTextSize(TypedValue.COMPLEX_UNIT_SP, 22.0f);

        String itemImageUrl = cursor.getString(cursor.getColumnIndex("logo"));
        if ((itemImageUrl != null) && (!itemImageUrl.isEmpty())) {
            Picasso.with(mContext)
                    .load(itemImageUrl)
                    .resize(300, 300)
                    .centerCrop()
                    .placeholder(R.drawable.placeholder)
                    .into(viewHolder.itemImage);
        } else {
            viewHolder.itemImage.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.placeholder));
        }
    }
}

上記のように、これは以下でテストおよび検証されています。

  • Nexus 6のマシュマロ(6.0.1):動作
  • Galaxy S5 の Lollipop (5.0):動作しない
  • Galaxy S3 の Jelly Bean (4.3):動作しない

ここで何か不足していますか?さらにどこを見るべきかについてのヒントはありますか?

4

1 に答える 1

3

回答がなかったので、この問題を回避するために最終的に何をしたかを説明します。

完全に書き直した後、skyfish の Cursor Adapter を取り除き、Android の RecyclerView インターフェイスをフルスロットルにしました。カーソル/アダプター スキームを使用して SQLite バックエンドからデータをプルし、基になるストレージに変更が加えられたときにカーソルをスワップする代わりに、ストレージ マネージャーでget-all-items静的メソッドを有効にして最新のデータを取得するだけです。データが変更されるたびにリストを更新するために、DBFlow のObservablesを使用してそのような変更の通知を受け取りました。変更が検出されたら、そのようなget-all-itemsを使用して更新されたデータを取得し、適切なnotifyItem()呼び出しを実行して RecyclerView を更新し、レイアウトの変更をアニメーション化します。

Android と DBFlow 以外の依存関係やコードを追加する必要はありません。このアプローチは、元の質問で説明されているすべてのデバイスで検証されています。

于 2016-03-30T08:09:42.847 に答える