当 App 被推送到后台并重新创建时,RecyclerView 不会恢复 LayoutManager 状态
When App is Pushed to the Background and Recreated, RecyclerView Not Restoring LayoutManager State
我最初关注 如何保存和恢复 RecyclerView 的布局管理器。
我在 Activity B 中有我的 RecyclerView。[注意:Activity A 将启动 Activity B,通过 intent 传输数据。]
当用户单击 Activity B 中的视窗时,将启动 Activity C。 Activity C 关闭并销毁后,Activity B 可见,我可以在 RecyclerView 中看到恢复的所有数据。
问题:
但是,如果我离开我的应用程序(即按 Home 键),它就会被推到后台。恢复我的应用程序后,将再次调用 onCreate() 。正在保存 LayoutManager 的状态,但是 none 我的数据显示在 RecyclerView 中。
我可以看出我的 LayoutManager 状态在一些调试后已保存。后台恢复应用后再次调用onCreate()显示如下:
Saved Instance State = Bundle[{ActivityB - Linear Layout State=android.support.v7.widget.LinearLayoutManager$SavedState@6358f8f, android:viewHierarchyState=Bundle[mParcelledData.dataSize=1296]}]
经过几个小时的尝试,我不确定如何解决这个问题。
我的代码:
public class ActivityB extends AppCompatActivity {
private RecyclerView recyclerView;
private LinearLayoutManager linearLayoutManager;
private Parcelable linearLayoutState;
private RecyclerAdapter adapter;
private Button more;
private String id;
private List<VideoItem> list;
private List<VideoItem> newList;
private final String LINEARLAYOUT_STATE_KEY = "Activity B - Linear Layout State";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blayout);
// Retrieving data from Activity A
Intent intent = getIntent();
Bundle bundle = intent.getBundleExtra("bundle");
someClass.innerClass class = bundle.getParcelable("data");
id = class.getID();
list = class.getList();
newList = new ArrayList<>();
// Instantiating Recycler View
recyclerView = (RecyclerView)findViewById(R.id.activityb_recyclerview);
recyclerView.setNestedScrollingEnabled(false);
linearLayoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(linearLayoutManager);
adapter = new RecyclerAdapter();
recyclerView.setAdapter(adapter);
moreButton = (Button)findViewById(R.id.activityb_more);
moreButton.setOnClickListener(new fetchMoreClickListener());
}
@Override
public void onResume(){
if (linearLayoutState != null) {
linearLayoutManager.onRestoreInstanceState(linearLayoutState);
} else {
// If no layout state is found, I need to populate my
// adapter.
// Here I am simply cloning my list again, to keep the original
// list intact. generateSubset() removes items from the cloned list
// to create a smaller subset that is added to the adapter.
for (ListItem item : list){
newList.add(new ListItemi(item));
}
adapter.addItems(generateSubset(0));
}
super.onResume();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
linearLayoutState = linearLayoutManager.onSaveInstanceState();
outState.putParcelable(LINEARLAYOUT_STATE_KEY, linearLayoutState);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
linearLayoutState = savedInstanceState.getParcelable(LINEARLAYOUT_STATE_KEY);
}
其他 Activity 生命周期方法没有被覆盖。我没有收到任何错误消息。只有我存储在我的 viewholders 中的数据不再显示在 RecyclerView 中。
编辑 1:
这是我的 RecyclerAdapter 代码:
public class RecyclerAdapter 扩展 RecyclerView.Adapter{
现在私人静态日期;
私有列表列表;
public static class ItemHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
private Context context;
private String key;
private Bundle itemBundle;
private SimpleDraweeView photo;
private TextView title;
public ItemHolder(Context context, View view){
super(view);
this.context = context;
this.key = null;
this.itemBundle = null;
photo = (SimpleDraweeView)view.findViewById(R.id.itemholder_photo);
title = (TextView)view.findViewById(R.id.itemholder_title);
view.setOnClickListener(this);
}
public void bindData(Item item){
if (key == null){ key = item.getID(); }
if (itemBundle == null){
itemBundle = new Bundle();
itemBundle.setClassLoader(Item.class.getClassLoader());
itemBundle.putParcelable("data", item);
}
photo.setImageURI(Uri.parse(item.getPhotoURL()));
}
@Override
public void onClick(View view) {
Intent intent = new Intent(context, ActivityB.class);
intent.putExtra("bundle", itemBundle);
context.startActivity(intent);
}
}
public RecyclerAdapter(){
this.list = new ArrayList<>();
this.now = new Date();
}
public RecyclerAdapter(ArrayList<VideoItem> list){
this.list = list;
this.now = new Date();
this.notifyItemRangeInserted(0, list.size());
}
@Override
public RecyclerAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
View recyclerItem = LayoutInflater.from(context)
.inflate(R.layout.itemholder_item, parent, false);
return new ItemHolder(context, recyclerItem);
}
@Override
public void onBindViewHolder(RecyclerAdapter.ItemHolder holder, int position) {
Item item = list.get(position);
holder.bindData(item);
}
private static Date getNow(){ return now; }
private static void updateNow(){ now = new Date(); }
@Override
public int getItemCount() {
return list.size();
}
public void addItem(Item item){
list.add(item);
this.notifyItemInserted(list.size() - 1);
}
public void addItems(ArrayList<Item> items){
int oldSize = list.size();
list.addAll(items);
this.notifyItemRangeInserted(oldSize, items.size());
}
}
尝试将您的 onResume()
方法更改为如下所示:
@Override
public void onResume(){
super.onResume();
if (linearLayoutState != null) {
linearLayoutManager.onRestoreInstanceState(linearLayoutState);
}
// Here comes the code to populate your data.
// I'm not sure how you do this, so I just copy/paste your code
for (ListItem item : list){
newList.add(new ListItemi(item));
}
// Now instatiate and add the adapter to the RecyclerView
adapter = new RecyclerAdapter(newList);
recyclerView.setAdapter(adapter);
}
}
我最初关注
我在 Activity B 中有我的 RecyclerView。[注意:Activity A 将启动 Activity B,通过 intent 传输数据。]
当用户单击 Activity B 中的视窗时,将启动 Activity C。 Activity C 关闭并销毁后,Activity B 可见,我可以在 RecyclerView 中看到恢复的所有数据。
问题: 但是,如果我离开我的应用程序(即按 Home 键),它就会被推到后台。恢复我的应用程序后,将再次调用 onCreate() 。正在保存 LayoutManager 的状态,但是 none 我的数据显示在 RecyclerView 中。
我可以看出我的 LayoutManager 状态在一些调试后已保存。后台恢复应用后再次调用onCreate()显示如下:
Saved Instance State = Bundle[{ActivityB - Linear Layout State=android.support.v7.widget.LinearLayoutManager$SavedState@6358f8f, android:viewHierarchyState=Bundle[mParcelledData.dataSize=1296]}]
经过几个小时的尝试,我不确定如何解决这个问题。
我的代码:
public class ActivityB extends AppCompatActivity {
private RecyclerView recyclerView;
private LinearLayoutManager linearLayoutManager;
private Parcelable linearLayoutState;
private RecyclerAdapter adapter;
private Button more;
private String id;
private List<VideoItem> list;
private List<VideoItem> newList;
private final String LINEARLAYOUT_STATE_KEY = "Activity B - Linear Layout State";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blayout);
// Retrieving data from Activity A
Intent intent = getIntent();
Bundle bundle = intent.getBundleExtra("bundle");
someClass.innerClass class = bundle.getParcelable("data");
id = class.getID();
list = class.getList();
newList = new ArrayList<>();
// Instantiating Recycler View
recyclerView = (RecyclerView)findViewById(R.id.activityb_recyclerview);
recyclerView.setNestedScrollingEnabled(false);
linearLayoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(linearLayoutManager);
adapter = new RecyclerAdapter();
recyclerView.setAdapter(adapter);
moreButton = (Button)findViewById(R.id.activityb_more);
moreButton.setOnClickListener(new fetchMoreClickListener());
}
@Override
public void onResume(){
if (linearLayoutState != null) {
linearLayoutManager.onRestoreInstanceState(linearLayoutState);
} else {
// If no layout state is found, I need to populate my
// adapter.
// Here I am simply cloning my list again, to keep the original
// list intact. generateSubset() removes items from the cloned list
// to create a smaller subset that is added to the adapter.
for (ListItem item : list){
newList.add(new ListItemi(item));
}
adapter.addItems(generateSubset(0));
}
super.onResume();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
linearLayoutState = linearLayoutManager.onSaveInstanceState();
outState.putParcelable(LINEARLAYOUT_STATE_KEY, linearLayoutState);
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
linearLayoutState = savedInstanceState.getParcelable(LINEARLAYOUT_STATE_KEY);
}
其他 Activity 生命周期方法没有被覆盖。我没有收到任何错误消息。只有我存储在我的 viewholders 中的数据不再显示在 RecyclerView 中。
编辑 1:
这是我的 RecyclerAdapter 代码:
public class RecyclerAdapter 扩展 RecyclerView.Adapter{ 现在私人静态日期; 私有列表列表;
public static class ItemHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
private Context context;
private String key;
private Bundle itemBundle;
private SimpleDraweeView photo;
private TextView title;
public ItemHolder(Context context, View view){
super(view);
this.context = context;
this.key = null;
this.itemBundle = null;
photo = (SimpleDraweeView)view.findViewById(R.id.itemholder_photo);
title = (TextView)view.findViewById(R.id.itemholder_title);
view.setOnClickListener(this);
}
public void bindData(Item item){
if (key == null){ key = item.getID(); }
if (itemBundle == null){
itemBundle = new Bundle();
itemBundle.setClassLoader(Item.class.getClassLoader());
itemBundle.putParcelable("data", item);
}
photo.setImageURI(Uri.parse(item.getPhotoURL()));
}
@Override
public void onClick(View view) {
Intent intent = new Intent(context, ActivityB.class);
intent.putExtra("bundle", itemBundle);
context.startActivity(intent);
}
}
public RecyclerAdapter(){
this.list = new ArrayList<>();
this.now = new Date();
}
public RecyclerAdapter(ArrayList<VideoItem> list){
this.list = list;
this.now = new Date();
this.notifyItemRangeInserted(0, list.size());
}
@Override
public RecyclerAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
View recyclerItem = LayoutInflater.from(context)
.inflate(R.layout.itemholder_item, parent, false);
return new ItemHolder(context, recyclerItem);
}
@Override
public void onBindViewHolder(RecyclerAdapter.ItemHolder holder, int position) {
Item item = list.get(position);
holder.bindData(item);
}
private static Date getNow(){ return now; }
private static void updateNow(){ now = new Date(); }
@Override
public int getItemCount() {
return list.size();
}
public void addItem(Item item){
list.add(item);
this.notifyItemInserted(list.size() - 1);
}
public void addItems(ArrayList<Item> items){
int oldSize = list.size();
list.addAll(items);
this.notifyItemRangeInserted(oldSize, items.size());
}
}
尝试将您的 onResume()
方法更改为如下所示:
@Override
public void onResume(){
super.onResume();
if (linearLayoutState != null) {
linearLayoutManager.onRestoreInstanceState(linearLayoutState);
}
// Here comes the code to populate your data.
// I'm not sure how you do this, so I just copy/paste your code
for (ListItem item : list){
newList.add(new ListItemi(item));
}
// Now instatiate and add the adapter to the RecyclerView
adapter = new RecyclerAdapter(newList);
recyclerView.setAdapter(adapter);
}
}