ViewPager2 迁移后出现无效 ID 0x00000001 错误
Posted
技术标签:
【中文标题】ViewPager2 迁移后出现无效 ID 0x00000001 错误【英文标题】:Invalid ID 0x00000001 errors after ViewPager2 migration 【发布时间】:2021-05-26 03:45:23 【问题描述】:我使用 ViewPager 处理选项卡布局已经有一段时间了,但它已被弃用。 我按照官方文档迁移到ViewPager2, 一切正常,但我在每个片段上都收到以下错误:
无效的 ID 0x00000001 无效的 ID 0x00000001 无效的 ID 0x00000001
每次我在片段之间滑动时,这些都会增加.. 没有崩溃,但每次我重新打开活动时,数字都会增加到 Invalid ID 0x00000002 等等。
我对消除此错误的解决方案感到迷茫,但该应用仍可与新的 ViewPager2 一起使用。 任何想法来解决错误垃圾邮件?
活动代码:
//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 代码:
//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();
布局活动:
<?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_
android:layout_
tools:context=".Loot.LootActivity">
<RelativeLayout
android:layout_
android:layout_>
<!-- Top Section (Toolbar) -->
<RelativeLayout
android:layout_
android:layout_
android:id="@+id/relLayout0">
<include
android:id="@+id/topViewBarHelper"
layout="@layout/snippet_top_profilebar"
android:layout_
android:layout_/>
</RelativeLayout>
<!-- Top Section (Toolbar) -->
<RelativeLayout
android:layout_
android:layout_
android:id="@+id/relLayout1"
android:layout_below="@+id/relLayout0">
<include layout="@layout/layout_top_tabs"/>
</RelativeLayout>
<!-- Middle Section (Body) -->
<RelativeLayout
android:layout_
android:layout_
android:id="@+id/relLayout2"
android:layout_below="@+id/relLayout1">
<include layout="@layout/layout_center_viewpager"/>
</RelativeLayout>
<RelativeLayout
android:layout_
android:layout_
android:id="@+id/relLayout3">
<!-- Bottom Section (Navigation) -->
<include layout="@layout/layout_bottom_navigation_view"/>
</RelativeLayout>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
布局中心查看器:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:layout_
android:layout_>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/container"
android:layout_
android:layout_
android:layoutDirection="ltr">
</androidx.viewpager2.widget.ViewPager2>
</RelativeLayout>
</merge>
布局顶部标签:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:layout_
android:layout_
android:layout_alignParentTop="true">
<com.google.android.material.appbar.AppBarLayout
android:layout_
android:layout_
android:id="@+id/AppBarLayout">
<com.google.android.material.tabs.TabLayout
android:layout_
android:layout_
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>
【问题讨论】:
同样的问题。 我遇到了同样的问题。有趣的是,它只出现在我的一台设备上,两台设备都运行 Android 11 (API 30)。在 Pixel 3a 上运行良好,在 OnePlus Nord 上获得Invalid ID 0x00000001
。
【参考方案1】:
更新
因此,在我更新我的 Android Studio IDE 和无效缓存后,问题似乎消失了:
文件 -> 使缓存无效/重新启动...
另外值得注意的是,我现在使用的是Android Studio Arctic Fox | 2020.3.1 Canary 10 Build #AI-203.7148.57.2031.7194378,于 2021 年 3 月 9 日构建
升级后,我删除了所有以前的模拟器,以确保问题出在我的代码上。到目前为止,日志已经尽可能干净了。如果有变化会再次更新。
原帖
当我在 YouTube 上遇到 video by Android Developers 时,我正试图自己解决这个问题。
我观看了它并按照讲师概述的步骤进行操作。在那个视频中,大约在2:50,教练说:
“...您现在将使用 createFragment 代替 viewPager1 中的 getItem,是的,我们希望您为特定位置创建一个新片段。”
这句话让我相信他是在建议我们为特定位置创建一个新片段,而不是存储和重用片段。
因此,我停止将片段列表传递给我的 FragmentStateAdapter 实现,而是在 Kotlin 中使用 when 表达式,您可以使用 switch/case 作为替代在 java 中也是如此。
我的示例只有两个片段,但我希望你能明白:
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 !
我的 TabLayoutMediator 看起来像这样:
TabLayoutMediator(tabLayout, viewPager, true ) tab, position ->
tab.text = when(position)
0 -> "Fragment1"
1 -> "Fragment2"
else -> "Unknown" // again, this case should not happen!
.attach()
但是,尽管 INVALID ID 消失了一段时间,但没过多久它又回来并开始填充我的调试控制台。这很奇怪,因为近一个月以来我一直以同样的方式使用 view pager2,这是我第一次遇到错误,即今天。
我注意到我的模拟器在错误出现之前闪烁了一次,我附上了一些在屏幕闪烁和无效 ID 开始出现之前出现的日志,以防万一有人能找到发生了什么。
>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.
这就是消息开始的时候。
此时我的猜测是,问题在于在创建/重新加载/恢复片段时未清除某些资源 ID。此外,应用程序不会崩溃或滞后,它只是在应用程序启动后 10 秒左右闪过一次屏幕,然后控制台中的混乱随之而来,UI 上什么也没有!
我把它放在这里,以便其他人可以阅读它并可能找到解决方案。
【讨论】:
以上是关于ViewPager2 迁移后出现无效 ID 0x00000001 错误的主要内容,如果未能解决你的问题,请参考以下文章
iOS 错误 - CGContextRestoreGState:无效上下文 0x0
在迁移到 viewpager2 androidx 时发现此错误“无法解析方法 'super(androidx.fragment.app.FragmentManager)'”