为什么 FragmentStateAdapter 在 ViewPager2 中不起作用?

Why FragmentStateAdapter not work in ViewPager2?

Android Studio 3.6

我想在我的 activity 中使用 ViewPager2 中的 2 个片段。

这是我的 activity:

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);
    }

}

这里是ViewPagerFragmentAdapter

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 中使用 FRAGMENTS

谢谢

FragmentStateAdapterViewPager2 中与在 ViewPager 中有点不同,如下所示:

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

  • 而不是实施 getItem(int position),实施 createFragment(int position)

  • 构造函数签名因添加 Lifecycle 参数而不同 也应该包含在 super 中

所以用下面的

替换你的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);
    }

}

还要确保 import/extend ViewPager2 的正确适配器

import androidx.viewpager2.adapter.FragmentStateAdapter;

2021 年更新

回答了原问题;但是,一般来说,以这种方式创建 FragmentStateAdapter 并不是那么正确;因为:

  1. 要获得高性能 ViewPager,它应该只保留一些实例化的屏幕外页面片段。

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

  3. createFragment(),顾名思义,意在为特定页面创建一个新的片段,并return它;不要 return 来自已经实例化片段的列表中的片段。

  4. 以上as per documentation createFragment()::

Provide a new Fragment associated with the specified position.

The adapter will be responsible for the Fragment lifecycle:

  • The Fragment will be used to display an item.
  • The Fragment will be destroyed when it gets too far from the viewport, and its state will be saved. When the item is close to the viewport again, a new Fragment will be requested, and a previously saved state will be used to initialize it.

因此,我建议更改此设计以将其纳入考虑范围:

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

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