From 7f7863b7be12dbdf8bfa038f6282bc1b0f3d6ab6 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sun, 11 Oct 2020 19:26:15 +0200 Subject: [PATCH] Generate unique view IDs --- .../antennapod/activity/MainActivity.java | 24 +++++++++++++++++++ .../fragment/ItemPagerFragment.java | 14 ++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java index eaa423708..fffe5be60 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -19,6 +19,7 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; +import androidx.core.view.ViewCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -67,6 +68,7 @@ public class MainActivity extends CastEnabledActivity { public static final String EXTRA_FEED_ID = "fragment_feed_id"; public static final String EXTRA_OPEN_PLAYER = "open_player"; public static final String EXTRA_REFRESH_ON_START = "refresh_on_start"; + public static final String KEY_GENERATED_VIEW_ID = "generated_view_id"; private DrawerLayout drawerLayout; private View navDrawer; @@ -88,6 +90,9 @@ public class MainActivity extends CastEnabledActivity { public void onCreate(Bundle savedInstanceState) { lastTheme = UserPreferences.getNoTitleTheme(); setTheme(lastTheme); + if (savedInstanceState != null) { + ensureGeneratedViewIdGreaterThan(savedInstanceState.getInt(KEY_GENERATED_VIEW_ID, 0)); + } super.onCreate(savedInstanceState); StorageUtils.checkStorageAvailability(this); setContentView(R.layout.main); @@ -132,6 +137,25 @@ public class MainActivity extends CastEnabledActivity { sheetBehavior.setBottomSheetCallback(bottomSheetCallback); } + /** + * ViewCompat.generateViewId stores the current ID in a static variable. + * When the process is killed, the variable gets reset. + * This makes sure that we do not get ID collisions + * and therefore errors when trying to restore state from another view. + */ + @SuppressWarnings("StatementWithEmptyBody") + private void ensureGeneratedViewIdGreaterThan(int minimum) { + while (ViewCompat.generateViewId() <= minimum) { + // Generate new IDs + } + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(KEY_GENERATED_VIEW_ID, ViewCompat.generateViewId()); + } + private BottomSheetBehavior.BottomSheetCallback bottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() { @Override diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java index c198ce258..b6e4190e8 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemPagerFragment.java @@ -38,6 +38,8 @@ import io.reactivex.schedulers.Schedulers; public class ItemPagerFragment extends Fragment { private static final String ARG_FEEDITEMS = "feeditems"; private static final String ARG_FEEDITEM_POS = "feeditem_pos"; + private static final String KEY_PAGER_ID = "pager_id"; + private ViewPager2 pager; /** * Creates a new instance of an ItemPagerFragment. @@ -77,12 +79,16 @@ public class ItemPagerFragment extends Fragment { feedItems = getArguments().getLongArray(ARG_FEEDITEMS); int feedItemPos = getArguments().getInt(ARG_FEEDITEM_POS); - ViewPager2 pager = layout.findViewById(R.id.pager); + pager = layout.findViewById(R.id.pager); // FragmentStatePagerAdapter documentation: // > When using FragmentStatePagerAdapter the host ViewPager must have a valid ID set. // When opening multiple ItemPagerFragments by clicking "item" -> "visit podcast" -> "item" -> etc, // the ID is no longer unique and FragmentStatePagerAdapter does not display any pages. int newId = ViewCompat.generateViewId(); + if (savedInstanceState != null && savedInstanceState.getInt(KEY_PAGER_ID, 0) != 0) { + // Restore state by using the same ID as before. ID collisions are prevented in MainActivity. + newId = savedInstanceState.getInt(KEY_PAGER_ID, 0); + } pager.setId(newId); pager.setAdapter(new ItemPagerAdapter(this)); pager.setCurrentItem(feedItemPos, false); @@ -99,6 +105,12 @@ public class ItemPagerFragment extends Fragment { return layout; } + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(KEY_PAGER_ID, pager.getId()); + } + @Override public void onDestroyView() { super.onDestroyView();