屏幕方向更改后恢复Android GridView(无需重新加载)

屏幕方向更改后恢复Android GridView(无需重新加载),android,gridview,screen-orientation,restore,android-configchanges,Android,Gridview,Screen Orientation,Restore,Android Configchanges,我是Android新手(这是我的第一个应用程序),我在活动中制作了一个GridView,我希望它能根据屏幕位置(纵向/横向)做出响应。当然,我为纵向和横向设置了一些自定义布局值GridViewrows width,效果非常好。 除此之外,在每次屏幕方向更改时,GridView将再次重新加载。这对用户体验不好。我只喜欢GridView(当然还有它的行)调整到新的屏幕宽度,而不需要执行所有onCreate()指令(从internet检索GridView的数据,在HashMap对象中分配退役数据,设置

我是Android新手(这是我的第一个应用程序),我在
活动中制作了一个
GridView
,我希望它能根据屏幕位置(纵向/横向)做出响应。当然,我为纵向和横向设置了一些自定义布局值
GridView
rows width,效果非常好。 除此之外,在每次屏幕方向更改时,
GridView
将再次重新加载。这对用户体验不好。我只喜欢
GridView
(当然还有它的行)调整到新的屏幕宽度,而不需要执行所有
onCreate()
指令(从internet检索
GridView
的数据,在
HashMap
对象中分配退役数据,设置
GridView
Adapter
,然后显示
GridView
的行)。 我浏览了许多论坛帖子和一些谷歌文档,其中谈到了如何恢复简单值,但在没有重新加载的情况下,从未找到恢复
GridView
的答案。 我读过关于
onSaveInstanceState()
onRestoreInstanceState()
,但我不知道如何在我的案例中使用它们(
GridView
案例)

有没有人能提供一个简单的代码示例?或者至少提供一些标题

以下是我在
活动
课程中在代码中尝试的一些内容:

    private Parcelable mListInstanceState;
    private Parcelable mAdapterInstanceState;

    private GridView gridView = null;
    private MyAdapter myAdapter = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       gridView = (GridView) findViewById(R.id.gridview);

       // Check whether we're recreating a previously destroyed instance
       if(savedInstanceState != null) {
            // Restore value of members from saved state
            mListInstanceState = savedInstanceState.getParcelable("gridview");
            mAdapterInstanceState = savedInstanceState.getParcelable("adapter");
       }
       else {
            // Retrieve data from internet, fill HashMap object, 
            // set Adapter and display GridView only for the first time the activity is created
            attemptToDisplayGirdViewItems();
       }
    }

    @Override
    protected void onSaveInstanceState(Bundle state) {
        // Save activity state

        super.onSaveInstanceState(state);

        state.putParcelable("gridview", gridView.onSaveInstanceState());
        // state.putParcelable("adapter", myAdapter);               
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        // Retrieve and restore activity state

        // Restore state members from saved instance
        mListInstanceState = savedInstanceState.getParcelable("gridview");
        mAdapterInstanceState = savedInstanceState.getParcelable("adapter");

        super.onRestoreInstanceState(savedInstanceState);
    }

您不需要保存视图。如果视图具有ID,它们将自动保存(例如GridView的滚动位置)。您需要保存的是适配器的数据集

您的适配器可能包含一个项列表。除非这些项是基本项或
String
或实现
Serializable
,否则它们需要实现
Parcelable
,才能工作

请参见此处的操作方法:

您的适配器需要一个
getItems
方法,该方法返回数据集—您的包裹项目的
ArrayList
。它还需要一个
setItems(…)
方法或一个以项目列表为参数的构造函数

然后,您的活动将如下所示:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
    gridView = (GridView) findViewById(R.id.gridview);

    myAdapter = new MyAdapter(); // Create empty adapter.
    if(savedInstanceState != null) {
        ArrayList<MyItem> items = savedInstanceState.getParcelableArrayList("myAdapter");
        myAdapter.setItems(items); // Load saved data if any.
    }
    gridView.setAdapter(myAdapter);
}

@Override
protected void onSaveInstanceState(Bundle state) {
    super.onSaveInstanceState(state);
    state.putParcelableArrayList("myAdapter", myAdapter.getItems());
}
@覆盖
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridView=(gridView)findViewById(R.id.gridView);
myAdapter=新建myAdapter();//创建空适配器。
如果(savedInstanceState!=null){
ArrayList items=savedInstanceState.getParcelableArrayList(“myAdapter”);
myAdapter.setItems(items);//加载保存的数据(如果有)。
}
setAdapter(myAdapter);
}
@凌驾
SaveInstanceState上受保护的无效(捆绑状态){
super.onSaveInstanceState(状态);
state.putParcelableArrayList(“myAdapter”,myAdapter.getItems());
}

您不需要保存视图。如果视图具有ID,它们将自动保存(例如GridView的滚动位置)。您需要保存的是适配器的数据集

您的适配器可能包含一个项列表。除非这些项是基本项或
String
或实现
Serializable
,否则它们需要实现
Parcelable
,才能工作

请参见此处的操作方法:

您的适配器需要一个
getItems
方法,该方法返回数据集—您的包裹项目的
ArrayList
。它还需要一个
setItems(…)
方法或一个以项目列表为参数的构造函数

然后,您的活动将如下所示:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
    gridView = (GridView) findViewById(R.id.gridview);

    myAdapter = new MyAdapter(); // Create empty adapter.
    if(savedInstanceState != null) {
        ArrayList<MyItem> items = savedInstanceState.getParcelableArrayList("myAdapter");
        myAdapter.setItems(items); // Load saved data if any.
    }
    gridView.setAdapter(myAdapter);
}

@Override
protected void onSaveInstanceState(Bundle state) {
    super.onSaveInstanceState(state);
    state.putParcelableArrayList("myAdapter", myAdapter.getItems());
}
@覆盖
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridView=(gridView)findViewById(R.id.gridView);
myAdapter=新建myAdapter();//创建空适配器。
如果(savedInstanceState!=null){
ArrayList items=savedInstanceState.getParcelableArrayList(“myAdapter”);
myAdapter.setItems(items);//加载保存的数据(如果有)。
}
setAdapter(myAdapter);
}
@凌驾
SaveInstanceState上受保护的无效(捆绑状态){
super.onSaveInstanceState(状态);
state.putParcelableArrayList(“myAdapter”,myAdapter.getItems());
}

您应该只保存数据(来自internet)…使用不推荐的
Activity.getLastNonfigurationInstance()保存数据
或使用UI较少的可保留片段…所有其他内容都应该在那里…GridView正在保存当前项在
onSaveInstanceState中的位置
因此您应该对此感到烦恼…检查CacheFragment类及其用法…从internet获取的数据存储在
JSONArray CacheFragment.response中
而且它在屏幕或显示更改中“存活”…loadData启动新请求或立即返回数据取决于
响应是否已设置感谢@Selvin的帮助。我尝试了Eugen的解决方案,效果很好:)savedInstanceState解决方案有一个小问题-savedInstanceState限制(~1MB) ... 所以你应该注意这个解决方案。。。此外,包裹/解包裹将占用一些CPU周期。。。当只保留一个实例时,不会-因为您将得到完全相同的数据实例。。。所以,当我不是说这是一个糟糕的解决方案时,我不会用它myself@Selvin:谢谢!这是Google文档中关于大数据和幸存的配置更改所说的:
…onSaveInstanceState()回调它不是为承载大对象(如位图)而设计的,其中的数据必须序列化然后反序列化,这会消耗大量内存并使配置更改变慢。您应该只保存(来自internet的)数据。。。使用已弃用的
Activity.getLastNonConfigurationInstance()
或使用UI较少的可保留片段的fx。。。所有其他的东西都应该在那里。。。GridView正在保存curre的位置