Как сохранить состояние фрагмента без стопки в закладке?

Я пытаюсь сохранить состояние фрагмента в onSaveInstanceState, но когда я возвращаюсь к фрагменту, он всегда перезагружается снова, а не начинается с последнего состояния.

Я просмотрел onCreateView и onActivityCreated и всегда имеет onSaveInstanceState как null.

public void navigateFragment(String tag, Fragment fragment,
        boolean shouldAdd) {

    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction ft = manager.beginTransaction();


    if (shouldAdd)
        mStacks.get(tag).push(fragment); // push fragment on stack

    ft.replace(android.R.id.tabcontent, fragment);

    if (shouldAdd)
        ft.addToBackStack(tag);

    ft.commit();

    }

Поскольку я не могу использовать backstack, потому что в вкладках back stack не полезен. Любая помощь будет высоко оценена.

Ответ 1

В этом случае вы должны сами управлять состояниями фрагментов. Я не знаю точно, как работает ваш код, поэтому единственное, что я могу сделать, это дать вам несколько советов.

Первое, что вам нужно реализовать, - сохранить состояние фрагмента. Предположим, что все фрагменты имеют уникальные идентификаторы. В этом случае вам нужно создать карту, которая будет содержать все состояния:

private final Map<String, Fragment.SavedState> mFragmentStates = new HashMap<>();

private void saveFragmentState(String id, Fragment fragment) {
    Fragment.SavedState fragmentState = 
            getSupportFragmentManager().saveFragmentInstanceState(fragment);
    mFragmentStates.put(id, fragmentState);
}

Вам нужно вызвать этот метод для фрагмента, который вы собираетесь удалить. Затем нам нужно восстановить состояние фрагмента и то, как мы можем это сделать:

private void restoreFragmentState(String id, Fragment fragment) {
    Fragment.SavedState fragmentState = mFragmentStates.remove(id);
    if (fragmentState != null) {
        fragment.setInitialSavedState(savedState);
    }
}

Этот метод необходимо вызвать перед добавлением фрагмента в транзакцию.

Предоставленный код должен работать нормально, но чтобы он корректно работал в режиме активного отдыха, нам необходимо правильно сохранить и восстановить mFragmentStates:

private static final String KEY_FRAGMENT_STATES = "fragment_states";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    /* Your code ... */

    if (savedInstanceState != null) {
        Bundle fragmentStates =
                savedInstanceState.getParcelable(KEY_FRAGMENT_STATES);
        if (fragmentStates != null) {
            for (String id : fragmentStates.keySet()) {
                Fragment.SavedState fragmentState =
                        fragmentStates.getParcelable(id);
                mFragmentStates.put(id, fragmentState);
            }
        }
    }
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    /* Your code ... */

    Bundle fragmentStates = new Bundle(mFragmentStates.size());
    for (Map.Entry<String, Fragment.SavedState> entry : mFragmentStates.entrySet()) {
        fragmentStates.put(entry.getKey(), entry.getValue());
    }
    outState.putParcelable(KEY_FRAGMENT_STATES, fragmentStates);
}

Также вы можете взглянуть на класс FragmentStatePagerAdapter. Он использует тот же подход для управления состояниями фрагментов ViewPager.

UPDATE. И поэтому ваш код должен выглядеть примерно так:

private Fragment mCurrentFragment;

public void navigateFragment(String tag, Fragment fragment,
        boolean shouldAdd) {
    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction transaction = manager.beginTransaction();

    if (shouldAdd) {
        mStacks.get(tag).push(fragment); // push fragment on stack
    }

    if (mCurrentFragment != null) {
        saveFragmentState(mCurrentFragment.getClass().getName(), mCurrentFragment);
    }

    mCurrentFragment = fragment;
    restoreFragmentState(fragment.getClass().getName(), fragment);
    transaction.replace(android.R.id.tabcontent, fragment);

    if (shouldAdd) {
        // You shouldn't use back-stack when managing fragment states by yourself.
        transaction.addToBackStack(tag);
    }

    transaction.commit();
}

В этом примере я использую имя класса фрагмента как id, поэтому весь фрагмент должен иметь разные классы. Но вы можете использовать любое другое уникальное значение как id. И еще одна важная вещь, которую я должен упомянуть, заключается в том, что вы не должны использовать back-stack при управлении состояниями фрагментов самостоятельно. Back-stack выполняет аналогичное управление состоянием, и у вас могут возникнуть конфликты.

Ответ 2

Я думаю, что вы должны использовать идею Общие предпочтения, это быстрее, чем использование локальных файлов или базы данных и, безусловно, проще кодировать. Хорошая веб-страница для Android @Параметры хранилища. Я приведу несколько примеров кода с веб-страницы и изменю несколько, чтобы удовлетворить ваши потребности.

Сначала получите данные, сохраненные из настроек в методе overCreate() override:

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

   SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
   boolean silent = settings.getBoolean("silentMode", false);
...
}

Затем сохраните данные до того, как фрагмент остановится или выйдет по различным причинам. Достигните это путем переопределения метода onDetach, вместо этого переопределите веб-страницу onStop().

@Override
public void onDetach() {
   super.onDetach();
   ...
   SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
   SharedPreferences.Editor editor = settings.edit();
   editor.putBoolean("silentMode", mSilentMode);

   // Commit the edits!
   editor.commit();
}

Удачи, получайте удовольствие!

Ответ 3

Вы делаете заменяете фрагмент, вот почему фрагмент уничтожается. Вы можете попробовать ниже. Здесь я делаю две вещи в одном FragmentTransaction, я добавляет новый фрагмент и скрывает существующий фрагмент.

Предположим, что мы добавляем фрагмент B поверх фрагмента A

    FragmentTransaction ft = fragmentManager.beginTransaction();
    ft.add(android.R.id.tabcontent, fragmentB, tagFragmentB)
            .hide(fragmentManager.findFragmentByTag(tagFragmentA))
            .addToBackStack(tag)
            .commit();

После того, как вы вернетесь, он будет удалить фрагмент B и показать фрагмент A с тем же (прежде чем добавить фрагмент B)

Обратите внимание: tagFragmentA и tagFragmentB - это теги, в которые добавляются фрагменты A и B соответственно p >

Ответ 4

Я не понимаю, какой вид вы используете для реализации вкладок. Я догадался,

ft.replace(android.R.id.tabcontent, fragment);

что вы, возможно, внедрили FragmentTabHost.

напишите customFragmentTabhost и переопределите

 @Override
public void onTabChanged(String tabId) {
    FragmentTransaction t = getSupportFragmentManager().beginTransaction();
    if (tabId.equals("Tab1")) {
        TabFragment1 fragment1 = null;
        if (getSupportFragmentManager().findFragmentByTag("Tab1") == null) {
            fragment1 = new TabFragment1();
        } else {
            fragment1 = (TabFragment1) getSupportFragmentManager().findFragmentByTag("Tab1");
        }
        t.replace(R.id.realContent, fragment1, "Tab1").addToBackStack(null).commit();
    }
}

UPDATE:

  • Убедитесь, что активность не воссоздана по ориентации, если установлено setRetainInstance (true), так что даже если активность будет воссоздана при изменении ориентации, фрагменты будут сохранены.

  • Предоставлять id для любых видов в фрагменте. Для системы Android важно поддерживать состояние.

Ответ 5

      clearBackStackEntry();
                        rl.setVisibility(View.GONE);

                        getSupportFragmentManager().beginTransaction()
                                .replace(FRAGMENT_CONTAINER, new HomeScreen())
                                .addToBackStack(null).commit();

     private void clearBackStackEntry() {
            int count = getSupportFragmentManager().getBackStackEntryCount();
            if (count > 0) {
                getSupportFragmentManager().popBackStack(null,
                        FragmentManager.POP_BACK_STACK_INCLUSIVE);
            }
        }



TRY THIS AND One more for fragment also try this: but use support.v4.app.Fragment, May be it will help you


Fragment fr = new main();
                android.support.v4.app.FragmentTransaction fragmentTransaction = getFragmentManager()
                        .beginTransaction();
                fragmentTransaction.replace(R.id.fragment_place, fr);
                fragmentTransaction.commit();
                // getActivity().finish();

Ответ 7

очень просто справиться с этими вещами. Я могу дать вам образец для обработки обратного нажатия на агенты Fr, которые мы добавили.

Я объявил стек фрагментов и нажимаю на него все фрагменты:

public static Stack<Fragment> fragmentStack;

создайте такой метод:

    public static void replaceFragementsClick(Fragment fragementObj,     Bundle bundleObj, String title){
        try {
            FragmentManager fragmentManager = ((FragmentActivity)     mContext).getSupportFragmentManager();
            if (fragementObj != null) {

            fragementObj.setArguments(bundleObj);
                fragmentManager.beginTransaction().replace(R.id.frame_container,     fragementObj).commit();
            } 

            DashBoardActivity.fragmentStack.push(fragementObj);


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Попробуйте также:

    public static void replaceFragementsClickBack(Fragment fragementObj, Bundle bundleObj, String title){
        try {
            FragmentManager fragmentManager = ((FragmentActivity) mContext).getSupportFragmentManager();
            if (fragementObj != null) {

            fragementObj.setArguments(bundleObj);
                fragmentManager.beginTransaction().replace(R.id.frame_container,     fragementObj).commit();

                DashBoardActivity.fragmentStack.pop();
            } 
        } catch (Exception e) {
            e.printStackTrace();
        }
}

В базовом активном действии, в котором вы добавили, отмените подавление, например:

@Override
    public void onBackPressed() {
            /**
             * Do Current Fragment Pop
             * */           
            fragmentStack.pop();            

            if(fragmentStack.size() >0){

                Bundle bunldeObj = new Bundle();
                //******Exit from Current Fragment
               Fragment fragment = fragmentStack.pop(); 
//                  fragmentStack.push(fragment);
                    if(fragment instanceof PhotosFragment){
                    bunldeObj.putString("position", "4");               
                    replaceFragementsClick(fragment,bunldeObj,"Photos");
                }else if(fragment instanceof PhotoDetatilFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Photos");
                }else if(fragment instanceof PhotoFullViewFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Photos");
                }else if(fragment instanceof HomeFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Home");
                }else if(fragment instanceof VideosFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Videos");
                }else if(fragment instanceof VideoDetailFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Videos");
                }else if(fragment instanceof VideoViewFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Videos");
                }else if(fragment instanceof MusicFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Music");
                }else if(fragment instanceof MusicListFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Music");
                }else if(fragment instanceof InstallAppsFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Apps");
                }else if(fragment instanceof MessageFragment){
                    bunldeObj.putString("position", "4");
                        replaceFragementsClick(fragment,bunldeObj,"Messages");
                }else if(fragment instanceof MessageDetailFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Messages");
                }else if(fragment instanceof LocateDeviceFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Locate     Device");
                }else if(fragment instanceof FilesFragmentBottomBar){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Files");
                }else if(fragment instanceof AppsFragment){
                    bunldeObj.putString("position", "4");
                    replaceFragementsClick(fragment,bunldeObj,"Apps");  



            }else {
                super.onBackPressed();

                Intent intent = new     Intent(DashBoardActivity.this,ConnectDeviceActivity.class);
                startActivity(intent);
                finish();
        }
    }