I have been working with a Tab layout with ViewPager for a while and it has gone deprecated. I followed the official documentation and migrated to ViewPager2, everything works but I am getting the following error on each fragment:
Invalid ID 0x00000001 Invalid ID 0x00000001 Invalid ID 0x00000001
And these will increase each time I slide between fragments.. No crash but every time I re-open the activity the number increases to Invalid ID 0x00000002 and so on.
I am lost with solutions to get this error away, but the app still works with the new ViewPager2. Any idea's to solve the error spam messages?
Activity code:
//Responsible for adding the 4 tabs: NewLoot, ActiveLoot, SharedLoot, FinishedLoot
private void setupViewPager(){
SectionsPagerAdapter adapter = new SectionsPagerAdapter(getSupportFragmentManager(),getLifecycle());
adapter.addFragment(new NewLootFragment());//index 0
adapter.addFragment(new ActiveLootFragment());//index 1
adapter.addFragment(new FinishedLootFragment());//index 2
ViewPager2 viewPager = (ViewPager2) findViewById(R.id.container);
viewPager.setAdapter(adapter);
final TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
new TabLayoutMediator(tabLayout, viewPager,
new TabLayoutMediator.TabConfigurationStrategy() {
@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
//tab.setText("OBJECT " + (position + 1));
}
}
).attach();
tabLayout.getTabAt(0).setIcon(R.drawable.ic_search);
tabLayout.getTabAt(1).setIcon(R.drawable.ic_arrow);
tabLayout.getTabAt(2).setIcon(R.drawable.ic_action_name);
tabLayout.getTabAt(0).getIcon().setColorFilter(getResources().getColor(R.color.red), PorterDuff.Mode.SRC_IN);
tabLayout.getTabAt(1).getIcon().setColorFilter(getResources().getColor(android.R.color.black), PorterDuff.Mode.SRC_IN);
tabLayout.getTabAt(2).getIcon().setColorFilter(getResources().getColor(android.R.color.black), PorterDuff.Mode.SRC_IN);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
tab.view.getTab().getIcon().setColorFilter(getResources().getColor(R.color.red), PorterDuff.Mode.SRC_IN);
} @Override
public void onTabUnselected(TabLayout.Tab tab) {
tab.view.getTab().getIcon().setColorFilter(getResources().getColor(android.R.color.black), PorterDuff.Mode.SRC_IN);
} @Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
SectionPagerAdapter code:
//Class that stores fragments for tabs
public class SectionsPagerAdapter extends FragmentStateAdapter {
private static String TAG = "SectionsPagerAdapter";
private final ArrayList<Fragment> mFragmentList = new ArrayList<>();
public SectionsPagerAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle){
super(fragmentManager, lifecycle);
}
//public ViewPagerFragmentAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
// super(fragmentManager, lifecycle);
//}
public void addFragment(Fragment fragment){
mFragmentList.add(fragment);
}
@NonNull
@Override
public Fragment createFragment(int position) {
return mFragmentList.get(position);
}
@Override
public int getItemCount() {
return mFragmentList.size();
}
}
Layout activity:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Loot.LootActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Top Section (Toolbar) -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/relLayout0">
<include
android:id="@+id/topViewBarHelper"
layout="@layout/snippet_top_profilebar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
<!-- Top Section (Toolbar) -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/relLayout1"
android:layout_below="@+id/relLayout0">
<include layout="@layout/layout_top_tabs"/>
</RelativeLayout>
<!-- Middle Section (Body) -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/relLayout2"
android:layout_below="@+id/relLayout1">
<include layout="@layout/layout_center_viewpager"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/relLayout3">
<!-- Bottom Section (Navigation) -->
<include layout="@layout/layout_bottom_navigation_view"/>
</RelativeLayout>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
layout center viewpager:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutDirection="ltr">
</androidx.viewpager2.widget.ViewPager2>
</RelativeLayout>
</merge>
layout top tabs:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentTop="true">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/AppBarLayout">
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tab_layout"
android:background="@drawable/white_grey_border_bottom"
app:tabIndicatorColor="@color/red"
app:tabIndicatorHeight="4dp">
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout>
</RelativeLayout>
</merge>
UPDATE
So it seems that the problem is gone after I updated my Android Studio IDE and Invalidated caches by going to:
File -> Invalidate caches / restart...
It is also worth noting that I am now using Android Studio Arctic Fox | 2020.3.1 Canary 10 Build #AI-203.7148.57.2031.7194378, built on March 9, 2021
After upgrading, I deleted all previous emulators just to be sure that the issue was with my code. As of now, the logs are as clean as they can get. Will update again if something changes.
Original Post
I was trying to fix this issue myself when I came across a video by Android Developers on YouTube.
I watched it and followed the steps outlined by the instructor. In that video, at around 2:50, the instructor says:
"...and instead of using getItem from viewPager1, you'll now use createFragment, and yes, we want you to create a new fragment for the specific position."
This statement leads me to believe that he is suggesting that we create a new fragment for the specific position, instead of storing and reusing the fragments.
Accordingly, I stopped passing the fragment list to my implementation of the FragmentStateAdapter, instead used the when expression in Kotlin, you can use the switch/case as an alternative for the same in java.
My sample has just two fragments, but I hope you get the idea:
class MyAdapter(activity: AppCompatActivity) : FragmentStateAdapter(activity) {
override fun getItemCount(): Int {
return 2 // I just wanted 2 fragments in my app
}
override fun createFragment(position: Int): Fragment {
return when(position){
0 -> Fragment1()
1 -> Fragment2()
else -> Fragment1() // this case should not happen but you can log it to debug console or do nothing {}!
}
}
}
And my TabLayoutMediator looks something like this:
TabLayoutMediator(tabLayout, viewPager, true ){ tab, position ->
tab.text = when(position){
0 -> "Fragment1"
1 -> "Fragment2"
else -> "Unknown" // again, this case should not happen!
}
}.attach()
However, even though the INVALID ID disappeared for a bit, it wasn't long before it came back and started filling my debug console. It's weird coz I have been working with view pager2 in the same manner since almost a month and this is the first I am encountering the error, i.e., today.
I have noticed that my emulator flashes once before the error appears, I am attaching a few of the logs that appeared right before the screen flashed and the Invalid ID's started showing up, just in case anyone can find what's up.
>mServiceHandler:Landroid/app/IntentService$ServiceHandler; (greylist, linking, allowed)
2021-03-15 21:08:42.046 9623-9623/com.kwaso.recorder W/.kwaso.recorde: Accessing hidden field Landroid/app/IntentService;->mRedelivery:Z (greylist-max-o, linking, denied)
2021-03-15 21:08:42.046 9623-9623/com.kwaso.recorder W/.kwaso.recorde: Accessing hidden field Landroid/app/IntentService;->mRedelivery:Z (greylist-max-o, linking, denied)
2021-03-15 21:08:42.057 9623-9623/com.kwaso.recorder W/.kwaso.recorde: Class android.os.PowerManager$WakeLock failed lock verification and will run slower.
2021-03-15 21:08:42.077 9623-9623/com.kwaso.recorder V/StudioProfiler: Profiler initialization complete on agent.
2021-03-15 21:08:42.079 9623-9737/com.kwaso.recorder V/StudioProfiler: Acquiring Application for Events
2021-03-15 21:08:42.083 9623-9738/com.kwaso.recorder W/InputMethodManager: InputMethodManager.getInstance() is deprecated because it cannot be compatible with multi-display. Use context.getSystemService(InputMethodManager.class) instead.
java.lang.Throwable
at android.view.inputmethod.InputMethodManager.getInstance(InputMethodManager.java:1234)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.tools.profiler.support.profilers.EventProfiler$InputConnectionHandler.run(EventProfiler.java:261)
at java.lang.Thread.run(Thread.java:923)
2021-03-15 21:08:42.084 9623-9738/com.kwaso.recorder W/InputMethodManager: InputMethodManager.peekInstance() is deprecated because it cannot be compatible with multi-display. Use context.getSystemService(InputMethodManager.class) instead.
java.lang.Throwable
at android.view.inputmethod.InputMethodManager.peekInstance(InputMethodManager.java:1253)
at android.view.inputmethod.InputMethodManager.getInstance(InputMethodManager.java:1239)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.tools.profiler.support.profilers.EventProfiler$InputConnectionHandler.run(EventProfiler.java:261)
at java.lang.Thread.run(Thread.java:923)
2021-03-15 21:08:45.429 9623-9623/com.kwaso.recorder D/FilesFragment: onViewCreated:
2021-03-15 21:08:45.464 9623-9740/com.kwaso.recorder D/UtilityFunctions: loadFilesInNewAPI:
2021-03-15 21:08:50.128 9623-9712/com.kwaso.recorder V/StudioTransport: Transport agent connected to daemon.
2021-03-15 21:08:50.293 9623-9717/com.kwaso.recorder V/StudioTransport: Handling agent command 1100 for pid: 9623.
2021-03-15 21:08:50.293 9623-9717/com.kwaso.recorder V/StudioTransport: JNIEnv not attached
2021-03-15 21:08:50.368 9623-9623/com.kwaso.recorder E/.kwaso.recorde: Invalid ID 0x00000000.
and that's when the messages start.
At this point my guess is that the issue is with some Resource ID's not being cleared when the fragments are being created/reloaded/resumed. Also, the app doesn't crash, or lags, its just one flash of screen around 10 seconds after the app starts and the mess in the console follows, nothing on the UI!
I am putting this out here so that other's can read it and possibly find a solution.
User contributions licensed under CC BY-SA 3.0