Merge pull request #4521 from ByteHamster/generate-unique-ids

Generate unique view IDs
This commit is contained in:
H. Lehmann 2020-10-11 22:06:27 +02:00 committed by GitHub
commit e4a714f2f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 1 deletions

View File

@ -19,6 +19,7 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.core.view.ViewCompat;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; 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_FEED_ID = "fragment_feed_id";
public static final String EXTRA_OPEN_PLAYER = "open_player"; public static final String EXTRA_OPEN_PLAYER = "open_player";
public static final String EXTRA_REFRESH_ON_START = "refresh_on_start"; 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 DrawerLayout drawerLayout;
private View navDrawer; private View navDrawer;
@ -88,6 +90,9 @@ public class MainActivity extends CastEnabledActivity {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
lastTheme = UserPreferences.getNoTitleTheme(); lastTheme = UserPreferences.getNoTitleTheme();
setTheme(lastTheme); setTheme(lastTheme);
if (savedInstanceState != null) {
ensureGeneratedViewIdGreaterThan(savedInstanceState.getInt(KEY_GENERATED_VIEW_ID, 0));
}
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
StorageUtils.checkStorageAvailability(this); StorageUtils.checkStorageAvailability(this);
setContentView(R.layout.main); setContentView(R.layout.main);
@ -132,6 +137,25 @@ public class MainActivity extends CastEnabledActivity {
sheetBehavior.setBottomSheetCallback(bottomSheetCallback); 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 = private BottomSheetBehavior.BottomSheetCallback bottomSheetCallback =
new BottomSheetBehavior.BottomSheetCallback() { new BottomSheetBehavior.BottomSheetCallback() {
@Override @Override

View File

@ -38,6 +38,8 @@ import io.reactivex.schedulers.Schedulers;
public class ItemPagerFragment extends Fragment { public class ItemPagerFragment extends Fragment {
private static final String ARG_FEEDITEMS = "feeditems"; private static final String ARG_FEEDITEMS = "feeditems";
private static final String ARG_FEEDITEM_POS = "feeditem_pos"; 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. * Creates a new instance of an ItemPagerFragment.
@ -77,12 +79,16 @@ public class ItemPagerFragment extends Fragment {
feedItems = getArguments().getLongArray(ARG_FEEDITEMS); feedItems = getArguments().getLongArray(ARG_FEEDITEMS);
int feedItemPos = getArguments().getInt(ARG_FEEDITEM_POS); int feedItemPos = getArguments().getInt(ARG_FEEDITEM_POS);
ViewPager2 pager = layout.findViewById(R.id.pager); pager = layout.findViewById(R.id.pager);
// FragmentStatePagerAdapter documentation: // FragmentStatePagerAdapter documentation:
// > When using FragmentStatePagerAdapter the host ViewPager must have a valid ID set. // > When using FragmentStatePagerAdapter the host ViewPager must have a valid ID set.
// When opening multiple ItemPagerFragments by clicking "item" -> "visit podcast" -> "item" -> etc, // When opening multiple ItemPagerFragments by clicking "item" -> "visit podcast" -> "item" -> etc,
// the ID is no longer unique and FragmentStatePagerAdapter does not display any pages. // the ID is no longer unique and FragmentStatePagerAdapter does not display any pages.
int newId = ViewCompat.generateViewId(); 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.setId(newId);
pager.setAdapter(new ItemPagerAdapter(this)); pager.setAdapter(new ItemPagerAdapter(this));
pager.setCurrentItem(feedItemPos, false); pager.setCurrentItem(feedItemPos, false);
@ -99,6 +105,12 @@ public class ItemPagerFragment extends Fragment {
return layout; return layout;
} }
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(KEY_PAGER_ID, pager.getId());
}
@Override @Override
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();