【发布时间】:2018-11-10 11:58:44
【问题描述】:
我尝试使用 ListView 以及 LoaderManager.LoaderCallbacks 和自定义 CursorAdapter 加载列表,它工作正常。但我正在尝试使用 RecyclerView 和自定义 RecyclerView.Adapter 来完成同样的任务,但我遇到了这个问题:
我第一次显示列表,但是当我旋转设备时,列表消失了。
这是代码,请看一下。
目录活动
public class CatalogActivity extends AppCompatActivity implements ItemAdapter.OnItemClickListener,
LoaderManager.LoaderCallbacks<Cursor> {
private static final int ITEMS_LOADER_ID = 1;
public static final String EXTRA_ITEM_NAME = "extra_item_name";
public static final String EXTRA_ITEM_STOCK = "extra_item_stock";
@BindView(R.id.list_items)
RecyclerView mListItems;
private ItemAdapter mItemAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_catalog);
ButterKnife.bind(this);
setupListItems();
getLoaderManager().initLoader(ITEMS_LOADER_ID, null, this);
}
private void setupListItems() {
mListItems.setHasFixedSize(true);
LayoutManager layoutManager = new LinearLayoutManager(this);
mListItems.setLayoutManager(layoutManager);
mListItems.setItemAnimator(new DefaultItemAnimator());
mListItems.addItemDecoration(new DividerItemDecoration(this, LinearLayout.VERTICAL));
mItemAdapter = new ItemAdapter(getApplicationContext(), this);
mListItems.setAdapter(mItemAdapter);
}
@Override
public void OnClickItem(int position) {
Intent intent = new Intent(this, EditorActivity.class);
Item item = mItemAdapter.getItems().get(position);
intent.putExtra(EXTRA_ITEM_NAME, item.getName());
intent.putExtra(EXTRA_ITEM_STOCK, item.getStock());
startActivity(intent);
}
private ArrayList<Item> getItems(Cursor cursor) {
ArrayList<Item> items = new ArrayList<>();
if (cursor != null) {
while (cursor.moveToNext()) {
int columnIndexId = cursor.getColumnIndex(ItemEntry._ID);
int columnIndexName = cursor.getColumnIndex(ItemEntry.COLUMN_NAME);
int columnIndexStock = cursor.getColumnIndex(ItemEntry.COLUMN_STOCK);
int id = cursor.getInt(columnIndexId);
String name = cursor.getString(columnIndexName);
int stock = Integer.parseInt(cursor.getString(columnIndexStock));
items.add(new Item(id, name, stock));
}
}
return items;
}
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle bundle) {
switch (loaderId) {
case ITEMS_LOADER_ID: {
String[] projection = {
ItemEntry._ID,
ItemEntry.COLUMN_NAME,
ItemEntry.COLUMN_STOCK
};
return new CursorLoader(
this,
ItemEntry.CONTENT_URI,
projection,
null,
null,
null
);
}
default:
return null;
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
mItemAdapter.setItems(getItems(cursor));
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
}
ItemAdapter
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemViewHolder> {
private ArrayList<Item> mItems;
private OnItemClickListener mOnItemClickListener;
private Context mContext;
public ItemAdapter(Context context, OnItemClickListener onItemClickListener) {
mOnItemClickListener = onItemClickListener;
mContext = context;
}
public void setItems(ArrayList<Item> items) {
if (items != null) {
mItems = items;
notifyDataSetChanged();
}
}
public ArrayList<Item> getItems() {
return mItems;
}
public interface OnItemClickListener {
void OnClickItem(int position);
}
public class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
@BindView(R.id.tv_item)
TextView tv_item;
@BindView(R.id.tv_stock)
TextView tv_stock;
public ItemViewHolder(@NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View view) {
int position = getAdapterPosition();
mOnItemClickListener.OnClickItem(position);
}
}
@NonNull
@Override
public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_inventory, parent, false);
return new ItemViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull ItemViewHolder itemViewHolder, int position) {
final Item item = mItems.get(position);
itemViewHolder.tv_item.setText(item.getName());
itemViewHolder.tv_stock.setText(mContext.getString(R.string.display_stock, item.getStock()));
}
@Override
public int getItemCount() {
if (mItems == null) {
return 0;
} else {
return mItems.size();
}
}
}
我无法弄清楚确切的问题。请帮忙。
【问题讨论】:
-
你做过调试吗?究竟是什么消失了?整个
RecyclerView,还是只是项目?您是否检查过LoaderCallbacks方法在轮换时正确运行?你检查过交付的Cursor的大小和内容吗?ArrayList正在构建中吗? -
@MikeM。整个 RecyclerView 明显消失了。你没看到上面的截图和解释吗?我调试发现在
getItems()方法while(cursor.moveToNext)在旋转后不起作用。加载器方法工作正常。 -
请准确解释整个
RecyclerView消失的原因。你完全没有提到这一点,特别是在你的描述中,截图无法传达这一点,因为没有项目的透明RecyclerView看起来与没有RecyclerView完全一样——一个空白的白框。无论如何,我不认为这就是你的意思。 -
那是模糊和模棱两可的,这就是我首先问这个的原因。什么是“清单”?是整个
RecyclerView本身在旋转后不显示,还是只是它没有任何项目? -
@MikeM。是的,这行得通! :) 它也保留了正确的滚动位置。请发布您的答案,以便我可以将其标记为正确,包括我在内的其他人可以投票。你能详细解释一下这个while和do-while问题吗?为什么会发生这种情况?是否还有其他需要开发人员处理这种情况的场景(示例)?谢谢! :)
标签: android android-recyclerview android-cursorloader android-loadermanager