微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ViewPager2 迁移后出现无效 ID 0x00000001 错误

如何解决ViewPager2 迁移后出现无效 ID 0x00000001 错误

我一直在使用 ViewPager 使用 Tab 布局,但它已被弃用。 我按照官方文档迁移到ViewPager2, 一切正常,但我在每个片段上收到以下错误

无效 ID 0x00000001 无效 ID 0x00000001 无效 ID 0x00000001

每次我在片段之间滑动时,这些都会增加.. 没有崩溃,但每次我重新打开活动时,数字都会增加到无效 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_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>

布局中心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>

布局顶部标签

<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>

解决方法

更新

因此,在我通过以下方式更新 Android Studio IDE 和无效缓存后,问题似乎消失了:

文件 -> 使缓存无效/重新启动...

另外值得注意的是,我现在使用的是Android Studio Arctic Fox | 2020.3.1 Canary 10 Build #AI-203.7148.57.2031.7194378,构建于2021年3月9日

升级后,我删除了所有以前的模拟器,以确保问题出在我的代码上。截至目前,日志已尽可能干净。如果有什么变化会再次更新。

原帖

当我在 YouTube 上遇到 videoAndroid Developers 时,我试图自己解决这个问题。

我观看了它并按照讲师概述的步骤进行了操作。在该视频中,大约在 2:50 时,讲师说:

“...而不是使用 viewPager1 中的 getItem,您现在将使用 createFragment,是的,我们希望您为特定位置创建一个新片段。”

这句话让我相信他是在建议我们为特定位置创建一个新片段,而不是存储和重复使用这些片段。

因此,我停止将片段列表传递给 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,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,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 上没有任何内容!

我把它放在这里是为了让其他人可以阅读它并可能找到解决方案。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。