Can';更改配置时,无法在Android中保存片段状态

Can';更改配置时,无法在Android中保存片段状态,android,android-fragments,parcelable,android-savedstate,Android,Android Fragments,Parcelable,Android Savedstate,这类问题在中国被问了很多次,所以我都试过了,但都没能达到我真正想要的。在我的应用程序中,我有一个片段,在片段中我有一个回收器视图回收视图将由我从API获得的数据进行操作 我想要的是,当旋转发生变化时,应用程序不会再次调用API。为了实现这一点,我知道我必须将数据放入onSaveInstanceState,如果我想保存一个复杂的对象,那么该类必须是implementsParcelable。我已经做了所有推荐的事情,但是没有达到我想要的 我在这里分享我的代码,我创建了一个简化的示例 SimpleFr

这类问题在中国被问了很多次,所以我都试过了,但都没能达到我真正想要的。在我的应用程序中,我有一个
片段
,在片段中我有一个
回收器
视图<代码>回收视图将由我从API获得的数据进行操作

我想要的是,当旋转发生变化时,应用程序不会再次调用API。为了实现这一点,我知道我必须将数据放入
onSaveInstanceState
,如果我想保存一个复杂的对象,那么该类必须是implements
Parcelable
。我已经做了所有推荐的事情,但是没有达到我想要的

我在这里分享我的代码,我创建了一个简化的示例

SimpleFragment.java的代码

public class SimpleFragment extends Fragment {

    RecyclerView recyclerView;
    ArrayList<TestModel> testModelList = new ArrayList<TestModel>() ;
    SimpleAdapter simpleAdapter;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.simple_fragment, container, false);
        recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler);

        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(mLayoutManager);

        simpleAdapter = new SimpleAdapter(getActivity());

        recyclerView.setAdapter(simpleAdapter);


        if(savedInstanceState != null){
            //if this fragment starts after a rotation or configuration change, load the existing model from a parcelable
            testModelList = savedInstanceState.getParcelableArrayList("key");
            // I have done necessary debug , after rotation , it comes here ,
            // but suddenly savedInstanceState becomes null and getTestModelList() get called


        }else {
            //if this fragment starts for the first time, load the list of model
           getTestModelList();
        }

        simpleAdapter.setModel(testModelList);

        return rootView;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelableArrayList("key",testModelList);
    }

    public void getTestModelList(){
        for (int i=0;i<10;i++){
            testModelList.add(new TestModel(i,"test"+i));
        }
        Toast.makeText(getActivity(),"Called",Toast.LENGTH_SHORT).show();
    }
}
公共类SimpleFragment扩展了片段{
回收视图回收视图;
ArrayList testModelList=新的ArrayList();
simpledapter simpledapter;
@可空
@凌驾
创建视图时的公共视图(LayoutFlater充气机、@Nullable ViewGroup容器、@Nullable Bundle savedInstanceState){
视图根视图=充气机。充气(R.layout.simple_碎片,容器,false);
recyclerView=(recyclerView)rootView.findViewById(R.id.recycler);
RecyclerView.LayoutManager mLayoutManager=新的LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager);
simpleAdapter=新的simpleAdapter(getActivity());
recyclerView.setAdapter(simpleAdapter);
如果(savedInstanceState!=null){
//如果此片段在旋转或配置更改后开始,请从包裹中加载现有模型
testModelList=savedInstanceState.getParcelableArrayList(“键”);
//我已经做了必要的调试,旋转后,它来到这里,
//但是savedInstanceState突然变为null并调用getTestModelList()
}否则{
//如果此片段是第一次启动,请加载模型列表
getTestModelList();
}
setModel(testModelList);
返回rootView;
}
@凌驾
SaveInstanceState上的公共无效(束超出状态){
super.onSaveInstanceState(超出状态);
outState.putParcelableArrayList(“key”,testModelList);
}
public void getTestModelList(){

对于(int i=0;i,您需要保存活动状态,并在配置之前检查它

请遵循此代码

public class MainActivity extends AppCompatActivity{


    private HomeFragment homeFragment;

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

        FragmentManager fm = getSupportFragmentManager();


           if (savedInstanceState == null) {
            homeFragment = new HomeFragment();


            ((fm.beginTransaction()).replace(R.id.mainframe, homeFragment)).commit();
        }
}}}

您需要保存活动的状态,并在配置之前进行检查

请遵循此代码

public class MainActivity extends AppCompatActivity{


    private HomeFragment homeFragment;

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

        FragmentManager fm = getSupportFragmentManager();


           if (savedInstanceState == null) {
            homeFragment = new HomeFragment();


            ((fm.beginTransaction()).replace(R.id.mainframe, homeFragment)).commit();
        }
}}}

您可以在Fragment
onCreate
方法中这样保存片段实例,以更改方向以保存实例:

@Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         // Set Instance true
        this.setRetainInstance(true);
    }

您可以在Fragment
onCreate
方法中这样保存片段实例,以更改方向以保存实例:

@Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         // Set Instance true
        this.setRetainInstance(true);
    }

Android会在方向改变时重新创建您的活动。这背后的原因是您可能需要更改布局,但您仍然可以通过
活动的
onConfiguration Changed()
片段来实现这一点,我建议您添加

android:configChanges=“方向|键盘隐藏|屏幕大小”


在您的清单文件中(请参阅和)。这将停止在Confifuration更改时重新创建活动。

Android会在方向更改时重新创建您的活动。这背后的原因是您可能需要更改布局,但您仍然可以使用
onConfigurationChanged()实现这一点
活动的
片段
我建议您添加

android:configChanges=“方向|键盘隐藏|屏幕大小”


在清单文件中(请参阅和)。这将停止在确认更改时重新创建活动。

谢谢,尝试过,但不起作用,方向更改时调用getTestModelList()函数。无需调用
getTestModelList()
method…当您的实例设置为
true
时,当您的方向更改时,它将保持您的状态
RecycleView.LayoutManager mLayoutManager=new LinearLayoutManager(getActivity());RecycleView.setLayoutManager(mLayoutManager);simpleAdapter=new simpleAdapter(getActivity());RecycleView.setAdapter(SimpleDatapter);getTestModelList();SimpleDatapter.setModel(testModelList)
这样做我没有显式调用它,这个方法会自动调用您是否尝试过我在评论中提到的以下代码?在manifest
android:configChanges=“orientation | screenSize”中的片段活动中这样设置谢谢,尝试过,但不起作用,getTestModelList()当方向更改时调用函数。无需调用
getTestModelList()
方法…当实例设置为
true
时,当方向更改时,它将保持您的状态
RecyclerView.LayoutManager mLayoutManager=new LinearLayoutManager(getActivity());RecyclerView.setLayoutManager(mLayoutManager);simpleAdapter=new simpleAdapter(getActivity());recyclerView.setAdapter(simpleAdapter);getTestModelList();simpleAdapter.setModel(testModelList)
这样做我没有显式地调用它,这个方法会自动调用您是否尝试过我在评论中提到的以下代码?在清单
android:configChanges=“orientation”| screenSize中的片段活动中这样设置
谢谢,我知道这一点,但是如果我想对横向使用单独的布局呢?在这种方法中,单独的布局不会加载。正如我所说,您仍然可以通过
onConfigurationChanged()实现这一点
callback。谢谢,我知道这一点,但是如果我想对横向使用单独的布局呢?在这种方法中,单独的布局不会加载。正如我所说,您仍然可以使用
onConfigurationCh实现这一点
public class MainActivity extends AppCompatActivity{


    private HomeFragment homeFragment;

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

        FragmentManager fm = getSupportFragmentManager();


           if (savedInstanceState == null) {
            homeFragment = new HomeFragment();


            ((fm.beginTransaction()).replace(R.id.mainframe, homeFragment)).commit();
        }
}}}
@Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         // Set Instance true
        this.setRetainInstance(true);
    }