提问者:小点点

为什么FragmentStateAdapter在ViewPager2中不起作用?[重复]


Android Studio 3.6

我希望在我的活动中使用ViewPager2中的2个片段。

这里我的活动:

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
public class QRBluetoothSwipeActivity extends AppCompatActivity {
    private ViewPager2 myViewPager2;
    private ViewPagerFragmentAdapter myAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        // Make sure this is before calling super.onCreate
        setTheme(R.style.AppTheme); // show splash screen
        super.onCreate(savedInstanceState);
        setContentView(R.layout.qr_bluetooth_swipe_activity);
        init();
    }

    private void init() {
        myAdapter = new ViewPagerFragmentAdapter(getSupportFragmentManager());
        myAdapter.addFragment(new BluetoothPageFragment());
        myAdapter.addFragment(new QrPageFragment());
        myViewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
        myViewPager2.setAdapter(myAdapter);
    }

}

这里查看页面片段适配器

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.viewpager2.adapter.FragmentStateAdapter;

import java.util.ArrayList;

public class ViewPagerFragmentAdapter  extends FragmentStateAdapter {

    private ArrayList<Fragment> arrayList = new ArrayList<>();

    public ViewPagerFragmentAdapter(@NonNull FragmentManager fragmentManager) {
        super(fragmentManager);
    }

    @NonNull
    @Override
    public Fragment getItem(int position) {
        return arrayList.get(position);
    }

    public void addFragment(Fragment fragment) {
        arrayList.add(fragment);
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }
}

但我得到了编译错误:

ViewPagerFragmentAdapter is not abstract and does not override abstract method createFragment(int) in FragmentStateAdapter

如何解决这个问题并在ViewPager2中使用碎片?

谢谢


共1个答案

匿名用户

< code>ViewPager2中的< code > FragmentStateAdapter 与< code>ViewPager中的略有不同,如下所示:

>

  • 不是实现getCount(),而是实现getItemCount()

    而不是实现getItem(int position),实现createFragment(int position)

    构造函数签名是不同的添加生命周期参数应该包括在超级

    因此,将您的ViewPagerFragmentAdapter替换为以下内容

    import androidx.annotation.NonNull;
    import androidx.fragment.app.Fragment;
    import androidx.fragment.app.FragmentManager;
    import androidx.lifecycle.Lifecycle;
    import androidx.viewpager2.adapter.FragmentStateAdapter;
    
    import java.util.ArrayList;
    
    
    public class ViewPagerFragmentAdapter extends FragmentStateAdapter {
    
        private ArrayList<Fragment> arrayList = new ArrayList<>();
    
        public ViewPagerFragmentAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
            super(fragmentManager, lifecycle);
        }
    
    
        public void addFragment(Fragment fragment) {
            arrayList.add(fragment);
        }
    
        @Override
        public int getItemCount() {
            return arrayList.size();
        }
    
        @NonNull
        @Override
        public Fragment createFragment(int position) {
            // return your fragment that corresponds to this 'position'
            return arrayList.get(position);
        }
    
    }
    

    还要确保导入/扩展ViewPage2的正确适配器

    import androidx.viewpager2.adapter.FragmentStateAdapter;
    

    这回答了问题的原始问题;然而,一般来说,以这种方式创建< code > FragmentStateAdapter 并不正确;因为:

    >

  • 要拥有高性能的ViewPager,它应该只保留一些实例化的屏幕外页面片段。

    将所有页面片段保留在一个列表中在浪费设备资源方面并不好。

    < code>createFragment(),顾名思义,旨在为特定页面创建一个新片段并返回它;不从已经实例化片段的列表中返回片段。

    最重要的是按照文档createFragment():

    提供与指定位置关联的新片段。

    适配器将负责片段生命周期:

    • 片段将用于显示项目
    • 当片段离视口太远时,它将被销毁,其状态将被保存。当项目再次靠近视口时,将请求一个新的片段,并使用先前保存的状态来初始化它

    因此,我建议更改此设计以将其考虑在内:

    假设您的页面片段是PageFragment;然后,您可以通过在<code>PageFragment</code>中使用<code>静态PageFragmentnewInstance(int position){}</code>方法来获得单实例模式,然后<code>createFragment()</code>应该是:

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        // return a brand new fragment that corresponds to this 'position'
        return PageFragment.newInstance(position); // Create a new instance of the page fragment
    }