Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/219.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android-保存/恢复片段状态_Android_Android Fragments_Fragment_Onresume_Back Stack - Fatal编程技术网

Android-保存/恢复片段状态

Android-保存/恢复片段状态,android,android-fragments,fragment,onresume,back-stack,Android,Android Fragments,Fragment,Onresume,Back Stack,我有一个活动,其中我经历了几个片段。在每个片段中,我都有几个视图(EditText、ListView、Map等) 如何保存此时显示的片段实例?当活动为onPause()-->onResume()时,我需要它工作。我还需要它在我从另一个片段(从Backback弹出)返回时工作 我从主活动中调用第一个片段,然后从片段中调用下一个片段 我的活动代码: public class Activity_Main extends FragmentActivity{ public static Fragment

我有一个活动,其中我经历了几个片段。在每个片段中,我都有几个视图(
EditText、ListView、Map
等)

如何保存此时显示的片段实例?当活动为
onPause()-->onResume()
时,我需要它工作。我还需要它在我从另一个片段(从Backback弹出)返回时工作

我从主
活动中调用第一个片段,然后从片段中调用下一个片段

我的活动代码:

public class Activity_Main extends FragmentActivity{

public static Fragment_1 fragment_1;
public static Fragment_2 fragment_2;
public static Fragment_3 fragment_3;
public static FragmentManager fragmentManager;

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

     fragment_1 = new Fragment_1();

     fragment_2 = new Fragment_2();

     fragment_3 = new Fragment_3();

     fragmentManager = getSupportFragmentManager();
     FragmentTransaction transaction_1 = fragmentManager.beginTransaction();
     transaction_1.replace(R.id.content_frame, fragment_1);
     transaction_1.commit();
}}
下面是我的一个片段的代码:

public class Fragment_1 extends Fragment {

      private EditText title;
      private Button go_next;


      @Override
      public View onCreateView(final LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) {

            View rootView = inflater.inflate(R.layout.fragment_1,
            container, false);

            title = (EditText) rootView.findViewById(R.id.title);

            go_next = (Button) rootView.findViewById(R.id.go_next);

            image.setOnClickListener(new View.OnClickListener() {

         @Override
         public void onClick(View v) {

                 FragmentTransaction transaction_2 = Activity_Main.fragmentManager
                .beginTransaction();

                 transaction_2.replace(R.id.content_frame,
                  Activity_Main.fragment_2);
                 transaction_2.addToBackStack(null);
                 transaction_2.commit();  

            });
        }}

我搜索了很多信息,但都不清楚。有人能给出一个明确的解决方案和一个例子吗

为了保存片段状态,您需要实现
onSaveInstanceState()
: “与活动一样,您可以使用捆绑包保留片段的状态,以防活动的进程被终止,并且在重新创建活动时需要恢复片段状态。您可以在片段的
onSaveInstanceState()
回调期间保存状态,并在
onCreate()期间恢复状态。”
onCreateView()
onActivityCreated()
。有关保存状态的详细信息,请参阅“活动”文档。“


当碎片移动到后台时,它不会被销毁。所有实例变量都保留在那里。这就是保存数据的地方。在创建的活动中检查以下条件:

  • 这是包裹!=无效的如果是,则保存数据的位置(可能是方向更改)
  • 实例变量中是否保存了数据?如果是的话,从他们那里恢复你的状态(或者什么都不做,因为一切都是应该的)
  • 否则您的片段将第一次显示,请重新创建所有内容
  • 编辑:这里有一个例子

    public class ExampleFragment extends Fragment {
        private List<String> myData;
    
        @Override
        public void onSaveInstanceState(final Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putSerializable("list", (Serializable) myData);
        }
    
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
    
            if (savedInstanceState != null) {
                //probably orientation change
                myData = (List<String>) savedInstanceState.getSerializable("list");
            } else {
                if (myData != null) {
                    //returning from backstack, data is fine, do nothing
                } else {
                    //newly created, compute data
                    myData = computeData();
                }
            }
        }
    }
    
    公共类ExampleFragment扩展了片段{
    私有列表数据;
    @凌驾
    SaveInstanceState上的公共无效(最终捆绑超出状态){
    super.onSaveInstanceState(超出状态);
    outState.putSerializable(“列表”,(可序列化)myData);
    }
    @凌驾
    已创建ActivityState上的公共无效(Bundle savedInstanceState){
    super.onActivityCreated(savedInstanceState);
    如果(savedInstanceState!=null){
    //可能是方向改变了
    myData=(列表)savedInstanceState.getSerializable(“列表”);
    }否则{
    if(myData!=null){
    //从后台返回,数据正常,什么也不做
    }否则{
    //新创建、计算数据
    myData=computeData();
    }
    }
    }
    }
    
    您可以从fragmentManager获取当前片段。如果在片段管理器中没有它们,您可以创建
    fragment\u 1

    public class MainActivity extends FragmentActivity {
    
    
        public static Fragment_1 fragment_1;
        public static Fragment_2 fragment_2;
        public static Fragment_3 fragment_3;
        public static FragmentManager fragmentManager;
    
    
        @Override
        protected void onCreate(Bundle arg0) {
            super.onCreate(arg0);
            setContentView(R.layout.main);
    
            fragment_1 = (Fragment_1) fragmentManager.findFragmentByTag("fragment1");
    
            fragment_2  =(Fragment_2) fragmentManager.findFragmentByTag("fragment2");
    
            fragment_3 = (Fragment_3) fragmentManager.findFragmentByTag("fragment3");
    
    
            if(fragment_1==null && fragment_2==null && fragment_3==null){           
                fragment_1 = new Fragment_1();          
                fragmentManager.beginTransaction().replace(R.id.content_frame, fragment_1, "fragment1").commit();
            }
    
    
        }
    
    
    }
    
    此外,您还可以使用
    setRetainInstance
    来确定它将执行的操作,它将忽略片段中的
    ondestory()
    方法,然后您的应用程序将返回后台,操作系统将终止您的应用程序,以分配更多内存,您需要将所有需要的数据保存在
    onSaveInstanceState
    捆绑包中

    public class Fragment_1 extends Fragment {
    
    
        private EditText title;
        private Button go_next;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true); //Will ignore onDestroy Method (Nested Fragments no need this if parent have it)
        }
    
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            onRestoreInstanceStae(savedInstanceState);
            return super.onCreateView(inflater, container, savedInstanceState);
        }
    
    
        //Here you can restore saved data in onSaveInstanceState Bundle
        private void onRestoreInstanceState(Bundle savedInstanceState){
            if(savedInstanceState!=null){
                String SomeText = savedInstanceState.getString("title");            
            }
        }
    
        //Here you Save your data
        @Override
        public void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putString("title", "Some Text");
        }
    
    }
    

    我不太确定这个问题是否仍然困扰着你,因为已经几个月了。但我想分享一下我是如何处理这件事的。 以下是源代码:

    int FLAG = 0;
    private View rootView;
    private LinearLayout parentView;
    
    /**
     * The fragment argument representing the section number for this fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";
    
    /**
     * Returns a new instance of this fragment for the given section number.
     */
    public static Fragment2 newInstance(Bundle bundle) {
        Fragment2 fragment = new Fragment2();
        Bundle args = bundle;
        fragment.setArguments(args);
        return fragment;
    }
    
    public Fragment2() {
    
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        Log.e("onCreateView","onCreateView");
        if(FLAG!=12321){
            rootView = inflater.inflate(R.layout.fragment_create_new_album, container, false);
            changeFLAG(12321);
        }       
        parentView=new LinearLayout(getActivity());
        parentView.addView(rootView);
    
        return parentView;
    }
    
    /* (non-Javadoc)
     * @see android.support.v4.app.Fragment#onDestroy()
     */
    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        Log.e("onDestroy","onDestroy");
    }
    
    /* (non-Javadoc)
     * @see android.support.v4.app.Fragment#onStart()
     */
    @Override
    public void onStart() {
        // TODO Auto-generated method stub
        super.onStart();
        Log.e("onstart","onstart");
    }
    
    /* (non-Javadoc)
     * @see android.support.v4.app.Fragment#onStop()
     */
    @Override
    public void onStop() {
        // TODO Auto-generated method stub
        super.onStop();
        if(false){
            Bundle savedInstance=getArguments();
            LinearLayout viewParent;
    
            viewParent= (LinearLayout) rootView.getParent();
            viewParent.removeView(rootView);
    
        }
        parentView.removeView(rootView);
    
        Log.e("onStop","onstop");
    }
    @Override
    public void onPause() {
        super.onPause();
        Log.e("onpause","onpause");
    }
    
    @Override
    public void onResume() {
        super.onResume();
        Log.e("onResume","onResume");
    }
    
    以下是主要活动:

    public class Activity_Main extends FragmentActivity{
    
    public static Fragment_1 fragment_1;
    public static Fragment_2 fragment_2;
    public static Fragment_3 fragment_3;
    public static FragmentManager fragmentManager;
    
    @Override
     protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
         fragment_1 = new Fragment_1();
    
         fragment_2 = new Fragment_2();
    
         fragment_3 = new Fragment_3();
    
         fragmentManager = getSupportFragmentManager();
         FragmentTransaction transaction_1 = fragmentManager.beginTransaction();
         transaction_1.replace(R.id.content_frame, fragment_1);
         transaction_1.commit();
    }}
    
    /**
     * Fragment managing the behaviors, interactions and presentation of the
     * navigation drawer.
     */
    private NavigationDrawerFragment mNavigationDrawerFragment;
    
    /**
     * Used to store the last screen title. For use in
     * {@link #restoreActionBar()}.
     */
    
    public static boolean fragment2InstanceExists=false;
    public static Fragment2 fragment2=null;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(R.layout.activity_main);
    
        mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager()
                .findFragmentById(R.id.navigation_drawer);
        mTitle = getTitle();
    
        // Set up the drawer.
        mNavigationDrawerFragment.setUp(R.id.navigation_drawer,
                (DrawerLayout) findViewById(R.id.drawer_layout));
    }
    
    @Override
    public void onNavigationDrawerItemSelected(int position) {
        // update the main content by replacing fragments
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
        switch(position){
        case 0:
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.replace(R.id.container, Fragment1.newInstance(position+1)).commit();
            break;
        case 1:
    
            Bundle bundle=new Bundle();
            bundle.putInt("source_of_create",CommonMethods.CREATE_FROM_ACTIVITY);
    
            if(!fragment2InstanceExists){
                fragment2=Fragment2.newInstance(bundle);
                fragment2InstanceExists=true;
            }
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.replace(R.id.container, fragment2).commit();
    
            break;
        case 2:
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.replace(R.id.container, FolderExplorerFragment.newInstance(position+1)).commit();
            break;
        default: 
            break;
        }
    }
    
    parentView
    是关键点。 通常,当
    onCreateView
    时,我们只使用return
    rootView
    。但是现在,我将rootView添加到
    parentView
    ,然后返回
    parentView
    。要防止“指定的子级已经有父级。您必须对…”错误调用
    removeView()
    ,我们需要调用
    parentView.removeView(rootView)
    ,否则我提供的方法无效。 我也想分享一下我是如何发现它的。首先,我设置了一个布尔值来指示实例是否存在。当实例存在时,
    rootView
    将不会再次膨胀。但是,logcat给了孩子已经有了父对象,所以我决定使用另一个父对象作为中间父视图。这就是它的工作原理

    希望对你有帮助

    试试这个:

    @Override
    protected void onPause() {
        super.onPause();
        if (getSupportFragmentManager().findFragmentByTag("MyFragment") != null)
            getSupportFragmentManager().findFragmentByTag("MyFragment").setRetainInstance(true);
    }
    
    @Override
    protected void onResume() {
        super.onResume();
        if (getSupportFragmentManager().findFragmentByTag("MyFragment") != null)
            getSupportFragmentManager().findFragmentByTag("MyFragment").getRetainInstance();
    }
    
    希望这会有所帮助

    您还可以将此项写入menifest文件中的活动标记:

      android:configChanges="orientation|screenSize"
    

    祝你好运

    Android fragment有一些优点也有一些缺点。 片段的最大缺点是,当您想要使用一个片段时,您需要创建一个片段。 使用它时,每次都会调用片段的
    onCreateView
    。如果您想在片段中保持组件的状态,您必须保存片段状态,并且您必须在下一个显示的窗口中加载其状态。 这使得片段视图有点慢和奇怪

    我找到了一个解决方案,我使用了这个解决方案:“一切都很好,每个人都可以尝试”

    第一次运行创建视图时,将视图创建为全局变量。第二次调用此片段时,再次调用此片段
    onCreateView
    ,您可以返回此全局视图。片段组件状态将保持不变

    View view;
    
    @Override
    public View onCreateView(LayoutInflater inflater,
            @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        setActionBar(null);
        if (view != null) {
            if ((ViewGroup)view.getParent() != null)
                ((ViewGroup)view.getParent()).removeView(view);
            return view; 
        }
        view = inflater.inflate(R.layout.mylayout, container, false);
    }
    
    如下文所述:

    您还可以像这样使用片段方法
    setRetainInstance(true)

    public class MyFragment extends Fragment {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // keep the fragment and all its data across screen rotation
            setRetainInstance(true);
    
        }
    }
    

    如果您使用底部栏而不是viewpager,您希望使用retrieve Previous save state设置自定义片段替换逻辑,您可以使用下面的代码

     String current_frag_tag = null;
     String prev_frag_tag = null;
    
    
    
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
       
    
            switch (tab.getPosition()) {
                case 0:
    
                    replaceFragment(new Fragment1(), "Fragment1");
                    break;
    
                case 1:
                    replaceFragment(new Fragment2(), "Fragment2");
                    break;
    
                case 2:
                    replaceFragment(new Fragment3(), "Fragment3");
                    break;
    
                case 3:
                   replaceFragment(new Fragment4(), "Fragment4");
                    break;
    
                default:
                    replaceFragment(new Fragment1(), "Fragment1");
                    break;
    
            }
    
        public void replaceFragment(Fragment fragment, String tag) {
            if (current_frag_tag != null) {
                prev_frag_tag = current_frag_tag;
            }
    
            current_frag_tag = tag;
    
    
            FragmentManager manager = null;
            try {
                manager = requireActivity().getSupportFragmentManager();
                FragmentTransaction ft = manager.beginTransaction();
    
                if (manager.findFragmentByTag(current_frag_tag) == null) { // No fragment in backStack with same tag..
                    ft.add(R.id.viewpagerLayout, fragment, current_frag_tag);
    
                    if (prev_frag_tag != null) {
                        try {
                            ft.hide(Objects.requireNonNull(manager.findFragmentByTag(prev_frag_tag)));
                        } catch (NullPointerException e) {
                            e.printStackTrace();
                        }
                    }
    //            ft.show(manager.findFragmentByTag(current_frag_tag));
                    ft.addToBackStack(current_frag_tag);
                    ft.commit();
    
                } else {
    
                    try {
                        ft.hide(Objects.requireNonNull(manager.findFragmentByTag(prev_frag_tag)))
                                .show(Objects.requireNonNull(manager.findFragmentByTag(current_frag_tag))).commit();
                    } catch (NullPointerException e) {
                        e.printStackTrace();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
    
    
    
        }
    
    在子片段内部,您可以使用下面的方法访问片段是否可见 注意:您必须在子片段中实现下面的方法


    你能举个例子吗?你想要什么样的例子?我描述的三个步骤的代码?第二个。实例变量中存储的信息在哪里?以及如何找回这些信息。谢谢。是否每次显示片段时都会调用onCreateView方法?正如你所看到的,我现在就在那里宣布我的观点。“我必须改变什么吗?”Stanete这篇文章是solu吗