Я пытаюсь реализовать сохранение и восстановление состояния, но у меня возникают проблемы при замене основного Fragment
на PreferenceFragment
, а затем нажатие кнопки "Назад" . Мой основной Fragment
состоит из ViewPager
с FragmentPagerAdapter
с 3 Fragments
для прокрутки. Ни один из Fragment.onCreateView()
обратных вызовов для моего 3 Fragment
не вызывается после нажатия кнопки "Назад" . Я пробовал все решения, которые я пришел сюда, на SO, но я не смог решить проблему.
Еще одна важная вещь, которую следует отметить, состоит в том, что данные для моего 3 ViewPager
Fragment
хранятся в отдельных классах, которые инстанцируются и доступны через Activity
. Все 3 Fragment
содержат RecyclerView
для перечисления большого количества данных. Это делается для чистоты, но также для сохранения этих данных в Activity
. Это, вероятно, не проблема, так как она отлично работает при запуске приложения, но также и потому, что главная проблема заключается в том, что мои Fragments
не воссозданы.
Неожиданное поведение:
При создании приложения все работает нормально, но когда я заменю основной Fragment
(содержащий ViewPager
с FragmentPagerAdapter
) другим, а затем нажав кнопку возврата, Fragment
в ViewPager
не воссозданы. Вызывается onCreateView()
моего основного Fragment
.
Вопросы:
Что мне не хватает? Должны ли быть созданы другие обратные вызовы? Где и как мне воссоздать Fragments
?
Что я пробовал:
- Изменено использование
FragmentAdapter
, но я должен использоватьgetSupportFragmentManager()
, как это было в здесь.
EDIT: использование ошибочных FragmentManager
на самом деле было источником моих проблем. См. Мой ответ ниже.
- Добавить
@Override public int getItemPosition(Object object) {return POSITION_NONE;}
кFragmentPagerAdapter
, как предложено здесь. - Измените
FragmentPagerAdapter
наFragmentStatePagerAdapter
, что не имеет значения здесь, насколько я понимаю. Внутренние элементыFragmentStatePagerAdapter
фактически сохраняютFragments
, но они не отображаются заново. - Добавьте основной
Fragment
назад с помощьюFragmentTransaction
, когда вызываетсяonCreateView()
и в нескольких других обратных вызовах этогоFragment
, см. нижеMMMainFragment
. - Различные вещи.
Мой класс MainFragment с соответствующим XML-макетом
public class MMMainFragment extends Fragment
{
private MMViewPager mMMViewPager = null;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Note that this method IS called when the back button is pressed.
// I have tried setting the content back to this instance in several places.
View view = inflater.inflate(R.layout.mm_main_fragment, container, false);
// Setup ViewPager.
mMMViewPager = (MMViewPager) view.findViewById(R.id.mm_pager);
TabLayout tabLayout = (TabLayout) view.findViewById(R.id.mm_tablayout);
tabLayout.setupWithViewPager(mMMViewPager);
return view;
}
public MMViewPager getMMViewPager()
{
return mMMViewPager;
}
}
mm_main_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.design.widget.TabLayout
android:id="@+id/mm_tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable" />
<com.mycompany.myapp.gui.mmpager.MMViewPager
android:id="@+id/mm_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
Тогда в Activity.onCreate()
я просто выполните:
// Insert Main Fragment.
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.mm_content_frame, new MMMainFragment())
.commit();
где mm_content_frame
является FrameLayout
, где я заменяю и удаляю Fragment
s. Затем, когда кнопка для просмотра настроек нажата, я запускаю следующий фрагмент ниже в Activity
. Я добавляю этот Fragment
в backstack, чтобы иметь возможность использовать кнопку "Назад" .
public void showSettingsFragment()
{
getSupportActionBar().setTitle(getString(R.string.mm_drawer_settings));
getSupportFragmentManager().beginTransaction()
.replace(R.id.mm_content_frame, new MMPreferencesFragment(), FragmentConstants.SETTINGS_FRAGMENT_TAG)
.addToBackStack(null)
.commit();
}
Клавиши MMViewPager:
public class MMViewPager extends ViewPager
{
private MMActivity mMMActivity;
private MMPagerAdapter mMMPagerAdapter;
public MMViewPager(Context context, AttributeSet attrs)
{
super(context, attrs);
mMMActivity = (MMActivity) context;
mMMPagerAdapter = new MMPagerAdapter(mMMActivity.getSupportFragmentManager(), mMMActivity);
this.setOffscreenPageLimit(PagerConstants.OFFSCREEN_PAGE_LIMIT);
this.setAdapter(mMMMPagerAdapter);
this.setCurrentItem(PagerConstants.PAGE_FILTER_RECIPES);
}
}
Класс MMPagerAdapter, в настоящее время FragmentStatePagerAdapter
:
public class MMPagerAdapter extends FragmentStatePagerAdapter
{
private MMActivity mMMActivity;
public MMPagerAdapter(FragmentManager fragmentManager, MMActivity mmActivity)
{
super(fragmentManager);
mMMActivity = mmActivity;
}
@Override
public Fragment getItem(int position)
{
switch (position)
{
case PagerConstants.PAGE_FILTER_RECIPES:
return new FilteredRecipesFragment();
case PagerConstants.PAGE_SELECTED_RECIPES:
return new SelectedRecipesFragment();
case PagerConstants.PAGE_SHOPPING_LIST:
return new ShoppingListFragment();
default:
return null;
}
}
@Override
public int getCount()
{
return PagerConstants.NUMBER_OF_PAGES; // 3
}
@Override
public CharSequence getPageTitle(int position)
{
switch (position)
{
case PagerConstants.PAGE_FILTER_RECIPES:
return mMMActivity.getResources().getString(R.string.mm_title_recipe_filter_fragment);
case PagerConstants.PAGE_SELECTED_RECIPES:
return mMMActivity.getResources().getString(R.string.mm_title_selected_recipes_fragment);
case PagerConstants.PAGE_SHOPPING_LIST:
return mMMActivity.getResources().getString(R.string.mm_title_shopping_list_fragment);
default:
return "Tab";
}
}
}
Для справки, здесь также основной макет Activity
:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/mm_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Source: http://developer.android.com/training/implementing-navigation/nav-drawer.html -->
<!-- The main content view -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Source: http://android-developers.blogspot.in/2014/10/appcompat-v21-material-design-for-pre.html -->
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mm_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:layout_alignParentTop="true"
style="@style/MMActionBar"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<!-- The FrameLayout where I replace Fragments -->
<FrameLayout
android:id="@+id/mm_content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/mm_toolbar"/>
</RelativeLayout>
<ListView
android:id="@+id/mm_drawer_listview"
android:layout_width="260dp"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingStart="16dp"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:background="@color/mm_white" />
</android.support.v4.widget.DrawerLayout>