DBFlow (SQLite) バックエンドから供給された RecyclerView リストを表示しようとしています。リスト内の各項目は、一度選択すると詳細アクティビティ ビューに遷移する項目を表します。他の CursorLoader と同様に、ビューをサポートする Loader で変更が発生するたびに、レイアウトが自動的に更新されることを期待しています。
これはMarshmallowでテストする場合には当てはまりますが、 LollipopとJelly 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):動作しない
ここで何か不足していますか?さらにどこを見るべきかについてのヒントはありますか?