简体   繁体   English

维护事务之间的片段实例状态

[英]Maintaining fragments instance state between transactions

From all the searches I have found on SO stating that you should save your instance state in the @Override public void onSaveInstanceState(Bundle outState) 从我在SO上发现的所有搜索中可以看出,您应将实例状态保存在@Override public void onSaveInstanceState(Bundle outState)

However This is tightly coupled with the activities lifestyle. 但是,这与活动生活方式紧密相关。

How can I save the state of my listview in a fragment that gets swapped out with another fragment. 如何将我的列表视图的状态保存在一个片段中,该片段被另一个片段替换掉。 I have one main activity which all the fragments are loaded into. 我有一个主要活动,所有片段都被加载到其中。

I have tried this so far: 到目前为止,我已经尝试过了:

    @Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    //Save adapter data so that when the fragment is returned to it can be resused.
    ArrayList<CategoryMobileDto> categories = new ArrayList<CategoryMobileDto>();
    for(int i=0; i < adapter.getCount();i++)
    {
        categories.add(adapter.getItem(i));
    }
    String persistData = new Gson().toJson(categories);
    outState.putString("Categories", persistData);        
}

and then in my OnCreate(); 然后在我的OnCreate();中

   if(savedInstanceState!=null)
    {
        String data =savedInstanceState.getString("Categories");
        Type collectionType = new TypeToken<ArrayList<CategoryMobileDto>>() {
        }.getType();
        adapter.addAll(gson.<Collection<CategoryMobileDto>>fromJson(data, collectionType));
        adapter.notifyDataSetChanged();
    }else{
       // Make request to server
    }

however savedInstanceState is always null. 但是savedInstanceState始终为null。 But this makes sense as my activity is not being destroyed and recreated. 但这是有道理的,因为我的活动没有被破坏和重建。

This is how I transition from one fragment to another: 这就是我从一个片段过渡到另一个片段的方式:

    fragment.setArguments(args);
    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.container, fragment, "ProductListFragment");
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();

Is there a way i can save the state of my listview when the fragment is removed and then restore it again when the fragment is popped from the back-stack? 有没有一种方法可以在删除片段时保存列表视图的状态,然后在从后堆栈弹出片段时再次恢复它的状态?

Move this code from onCreate() to onActivityCreated() of Fragment 将此代码从Fragment的onCreate()移到onActivityCreated()

if(savedInstanceState!=null)
    {
        String data =savedInstanceState.getString("Categories");
        Type collectionType = new TypeToken<ArrayList<CategoryMobileDto>>() {
        }.getType();
        adapter.addAll(gson.<Collection<CategoryMobileDto>>fromJson(data, collectionType));
        adapter.notifyDataSetChanged();
    }else{
       // Make request to server
    }

If you have any query please let me know. 如果您有任何疑问,请告诉我。

You can use the Arguments with the Fragment(Only if you have the data to show in fragment before the fragment is loaded means attached). 您可以将Arguments与Fragment一起使用(仅当您有数据要在片段加载之前以片段形式显示时才附加)。 You can setArguments to a fragment which will be persisted when you go to another fragment by fragment transaction and when you come back, load the fragment from the getArguments function. 您可以将Arguments设置为一个片段,当您通过片段事务转到另一个片段时,该片段将保留下来,当您回来时,可以从getArguments函数中加载片段。

public void setArguments (Bundle args) 公共无效setArguments(捆绑参数)

Added in API level 11 Supply the construction arguments for this fragment. API级别11中添加了为此片段提供构造参数。 This can only be called before the fragment has been attached to its activity; 这只能在片段附加到其活动之前被调用; that is, you should call it immediately after constructing the fragment. 也就是说,您应该在构建片段后立即调用它。 The arguments supplied here will be retained across fragment destroy and creation. 此处提供的参数将在片段销毁和创建过程中保留。

public final Bundle getArguments () 公共最终捆绑包getArguments()

Added in API level 11 Return the arguments supplied when the fragment was instantiated, if any. 在API级别11中添加。返回实例化片段时提供的参数(如果有)。

Please find the sample code below for passing data between fragments : 请在下面找到用于在片段之间传递数据的示例代码:

main.xml main.xml中

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/flContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" >

</FrameLayout>

MainActivity.java MainActivity.java

public class MainActivity extends Activity implements IFragContainer {

private static final String FRAG_TAG = "FragTag";
private FragBase mFrag;
private String dataToBePassedBack;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    changeFragment(FragA.class, "Data to Frag A");
}

@Override
public void changeFragment(Class<? extends FragBase> fragClass, String data) {
    try {
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        mFrag = fragClass.newInstance();
        Bundle args = new Bundle();
        args.putString("DATA", data);
        mFrag.setArguments(args);
        ft.replace(R.id.flContainer, mFrag, FRAG_TAG);
        ft.addToBackStack(mFrag.toString());
        ft.commit();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public void onBackPressed() {
    dataToBePassedBack = mFrag.getDataToPassBack();
    FragmentManager mgr = getFragmentManager();
    mgr.executePendingTransactions();

    boolean doCheckAndExit = true;

    for (int i = mgr.getBackStackEntryCount() - 1; i > 0; i--) {
        BackStackEntry entry = mgr.getBackStackEntryAt(i);

        if (!TextUtils.isEmpty(entry.getName())) {
            mgr.popBackStackImmediate(entry.getId(),
                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
            doCheckAndExit = false;
            break;
        }
    }

    if (doCheckAndExit) {
        finish();
    } else {
        mFrag = (FragBase) mgr.findFragmentByTag(FRAG_TAG);
    }
}

@Override
public String getDataToBePassedBack() {
    return dataToBePassedBack;
}

}

IFragContainer.java IFragContainer.java

public interface IFragContainer {
void changeFragment(Class<? extends FragBase> fragClass, String data);

String getDataToBePassedBack();
}

FragBase.java FragBase.java

public abstract class FragBase extends Fragment {

public String getDataToPassBack(){
    return null;
}

}

FragA.java FragA.java

public class FragA extends FragBase {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Button btn = new Button(getActivity());
    final IFragContainer fragContainer = (IFragContainer) getActivity();
    if (TextUtils.isEmpty(fragContainer.getDataToBePassedBack())) {
        btn.setText(getArguments().getString("DATA"));
    } else {
        btn.setText(fragContainer.getDataToBePassedBack());
    }
    btn.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
            LayoutParams.WRAP_CONTENT));
    btn.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            fragContainer.changeFragment(FragB.class, "Data to Frag B");
        }
    });
    return btn;
}

}

FragB.java FragB.java

public class FragB extends FragBase {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Button btn = new Button(getActivity());
    btn.setText(getArguments().getString("DATA"));
    btn.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
            LayoutParams.WRAP_CONTENT));
    btn.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            getActivity().onBackPressed();
        }
    });
    return btn;
}

@Override
public String getDataToPassBack() {
    return "Data from Frag B to A";
}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM