ViewPager Fragments werden nicht neu erstellt, nachdem FragmentTransaction.ersetzen (), gefolgt vom zurück-button
Ich versuche zu implementieren, speichern und wiederherstellen des Status, jedoch habe ich Probleme beim Austausch der wichtigsten Fragment
mit einem PreferenceFragment
und dann schlagen die zurück-Taste. Mein main Fragment
besteht aus einem ViewPager
mit einem FragmentPagerAdapter
mit 3 Fragments
zu streichen, durch. Keiner der Fragment.onCreateView()
Rückrufe für meine 3 Fragment
s aufgerufen werden, nach dem drücken der Schaltfläche "zurück". Ich habe versucht, alle Lösungen, die ich habe, kommen hier drüben SO ist, aber ich habe nicht in der Lage, das Problem zu beheben.
Andere eventuell wichtige Sache zu beachten ist, dass die Daten für meine 3 ViewPager
Fragment
s gespeichert werden, in separaten Klassen, die instanziert sind und der Zugriff über die Activity
. Die 3 Fragment
s enthalten alle RecyclerView
s für die Auflistung eine ganze Menge Daten. Dies geschieht für die Sauberkeit, aber auch so, dass diese Daten weiterhin in der Activity
. Dies ist wahrscheinlich kein Problem, da funktioniert es einwandfrei, beim starten der app, aber auch da das Hauptproblem ist, dass meine Fragments
sind nicht neu.
Unerwartetes Verhalten:
Auf Anwendungen zu erstellen, alles funktioniert einwandfrei, aber wenn ich ersetzen mein main Fragment
(mit einem ViewPager
mit einem FragmentPagerAdapter
) mit einem anderen ein und dann drücken Sie die Taste zurück, die Fragment
s in der ViewPager
sind nicht neu. Die onCreateView()
meiner wichtigsten Fragment
ist genannt.
Fragen:
Was bin ich? Gibt es eine andere Rückrufe, die erstellt werden soll? Wo und wie soll ich das neu erstellen der Fragments
?
Was habe ich versucht:
- Geändert
FragmentAdapter
im Einsatz, aber ich sollte wirklich verwendengetSupportFragmentManager()
wie war die Lösung hier.
EDIT: die Nutzung fehlerhafter FragmentManager
eigentlich war die Quelle meiner Probleme. Siehe meine Antwort unten.
- Hinzufügen
@Override public int getItemPosition(Object object) {return POSITION_NONE;}
derFragmentPagerAdapter
wie vorgeschlagen hier. - Ändern von
FragmentPagerAdapter
zuFragmentStatePagerAdapter
sollte nicht Sache hier, soweit ich das verstanden habe. Die InternaFragmentStatePagerAdapter
tatsächlich hält dieFragments
, aber Sie sind nicht neu zu erbringen. - Fügen Sie die wichtigsten
Fragment
hinten mit einerFragmentTransaction
wenn seineonCreateView()
genannt wird und in mehreren anderen Rückrufe derFragment
finden SieMMMainFragment
unten. - Verschiedene andere Dinge.
Meine MainFragment Klasse mit entsprechenden XML-layout
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>
Dann, in Activity.onCreate()
ich einfach:
//Insert Main Fragment.
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.mm_content_frame, new MMMainFragment())
.commit();
wo mm_content_frame
ist ein FrameLayout
wo ich ersetzen und entfernen Fragment
s. Dann, wenn eine Schaltfläche, um die Einstellungen sind gedrückt, ich führen Sie den folgenden Codeausschnitt unten in der Activity
. Ich füge diese Fragment
auf den backstack zu können, verwenden Sie die zurück-Taste.
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();
}
Die MMViewPager clas:
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);
}
}
Die MMPagerAdapter Klasse, derzeit eine 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";
}
}
}
Für Referenz, hier ist auch die main-layout der 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>
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nach kämpfen mit diesem für ein paar Tage, erkannte ich, dass das problem tatsächlich war, dass ich an der falschen
FragmentManager
zu denViewPager
. Es ist in der Tat dieFragmentManager
zurückgegebenFragment.getChildFragmentManager()
verwendet werden soll. Dies macht Sinn, da es dieFragment
selbst, speichert den Zustand des KindesFragment
s in derViewPager
. Ich bin mir nicht sicher, warum ich es nicht machen, dass die Arbeit vor, aber jetzt ist der Lebenszyklus der app funktioniert gut mit den folgenden Einstellungen in meinem Haupt -Fragment
'sonCreate()
Methode:War dies auch die Lösung von eine andere Frage. Als seitliche Anmerkung, ich benutze diese Lösung, um die
Fragment
s in meinemViewPager
und es funktioniert gut mit dem Lebenszyklus.Test Anwendung:
In der Forschung dieses Problems erstellte ich eine test-Anwendung für diese. Diejenigen, die interessiert es sich Klonen von hier. Es hat hässliche Farben.
android.support.v4.app
?android.support.v4.app
, aber das fragment ist normal-Fragment.android.support.v4.app.Fragment
und Sie sollten gut zu gehen. Wenn Sie die Unterstützung für ältere Android-Versionen verwenden Sie die support-Bibliotheken.Soweit, ich verstehe, du hast dein problem gelöst. Ich habe vor ein ganz ähnliches Problem in der Vergangenheit. Vielleicht helfen Sie anderen, die versuchen, etwas ähnliches.
Die Sache, die mir geholfen haben, um weiterhin mein fragment Zustand war, zu ersetzen, die
Methode von meinem adapter.
Ich die
Adapter
damitHashMap
vonFragment
. Auf diese Weise werden die Fragmente einmal erstellt, und dann werden aus der HashMap. Abhängig von Ihrer Struktur können Sie eineArrayList
statt der HashMap.Dies ist eine leistungsfähige und "intelligente" Art und Weise der Umsetzung
getItemPosition(Object object)
zureturn POSITION_NONE;
oder die richtige position des Elements.Weiß ich wirklich nicht, wenn ich hatte die
getChildFragmentManager
im adapter oder nicht.Ich vermute, dass könnte ich Graben sich in mein Dateisystem, wenn Sie weitere Informationen benötigen 🙂
Fragment
s aktuell gespeicherten in derViewPager
. Ihre Lösung ist praktikabel, soweit ich weiß. Ich benutze this Lösung um dieses Problem zu lösen mich.