Android开发 - (适配器)Adapter类中FragmentPagerAdapter实现类详细解析
简介
- 用于 ViewPager,与 Fragment 一起使用,适合少量静态页面
具体作用
-
FragmentPagerAdapter 专用于在 ViewPager 中管理和显示 Fragment。它允许你在滑动视图(ViewPager)中实现分页功能,每个页面都是一个 Fragment。FragmentPagerAdapter 适用于需要管理少量 Fragment 的场景,因为它会将所有的 Fragment 一次性加载到内存中,保持它们的生命周期,避免频繁地创建和销毁 Fragment。它的主要用途为:
分页显示
- FragmentPagerAdapter 允许在 ViewPager 中展示多个 Fragment,并通过左右滑动进行页面切换
管理 Fragment 生命周期
- 通过 FragmentPagerAdapter,每个 Fragment 只会创建一次保持在内存中,这样可以更有效地管理 Fragment 的生命周期,避免频繁的销毁和重建
适用于少量 Fragment
- FragmentPagerAdapter 适合于 Fragment 数量较少的情况(通常少于 5 个),因为它会将所有 Fragment 对象保存在内存中
参数、方法解析
-
FragmentPagerAdapter(FragmentManager fm);
:基本的构造方法,适用于早期的 Android 版本。FragmentManager 用于在适配器中添加、移除或替换 Fragment。抽象类无法直接实例化,需要重写一个子类继承它public class MyPagerAdapter extends FragmentPagerAdapter { private int numOfTabs; // 自定义参数:Fragment 的总数量 // 自定义构造方法:接受 FragmentManager、自定义参数:Fragment 的总数量 public MyPagerAdapter(@NonNull FragmentManager fm, int numOfTabs) { super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); this.numOfTabs = numOfTabs; } @NonNull @Override public Fragment getItem(int position) { // 根据 position 返回对应的 Fragment 对象 return PageFragment.newInstance(position + 1); } //重写方法并导入 Fragment 的总数量 @Override public int getCount() { // 返回 Fragment 的总数量 return numOfTabs; } } // 实例化,并传入 FragmentManager 和 tab 的数量 MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), 3);
- 参数解析:
- fm:用于与 Fragment 进行交互。可以是 FragmentActivity 中的
getSupportFragmentManager();
,也可以是 Fragment 中的getChildFragmentManager();
- fm:用于与 Fragment 进行交互。可以是 FragmentActivity 中的
- 参数解析:
-
FragmentPagerAdapter(FragmentManager fm, int behavior);
:此构造方法允许你指定适配器的行为模式,从而更好地控制 Fragment 的生命周期管理,抽象类无法直接实例化,需要重写一个子类继承它public class MyPagerAdapter extends FragmentPagerAdapter { private int numOfTabs; // 自定义参数:Fragment 的总数量 // 自定义构造方法:接受 FragmentManager、自定义参数:Fragment 的总数量 public MyPagerAdapter(@NonNull FragmentManager fm, int numOfTabs) { super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); // 直接使用 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,在实例化时就不需要重复操作了 this.numOfTabs = numOfTabs; } @NonNull @Override public Fragment getItem(int position) { // 根据 position 返回对应的 Fragment 对象 return PageFragment.newInstance(position + 1); } //重写方法并导入 Fragment 的总数量 @Override public int getCount() { // 返回 Fragment 的总数量 return numOfTabs; } } // 实例化,并传入 FragmentManager 和 tab 的数量 MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), 3);
- 参数解析:
- fm:用于与 Fragment 进行交互。可以是 FragmentActivity 中的
getSupportFragmentManager();
,也可以是 Fragment 中的getChildFragmentManager();
- behavior:表示适配器的行为类型;可以是以下常量之一:
- FragmentStatePagerAdapter.BEHAVIOR_SET_USER_VISIBLE_HINT:在 API 24 及更低版本中使用,这种行为控制 Fragment 的可见性
- FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT:推荐使用的行为模式,表示只有当前可见的 Fragment 会被设置为活动状态(Resumed)
- fm:用于与 Fragment 进行交互。可以是 FragmentActivity 中的
- 参数解析:
-
adapter.instantiateItem(ViewGroup container, int position);
:根据给定的位置创建 Fragment 对象并将其添加到 container 中- 参数解析:
- container:ViewGroup,即 ViewPager,用于将新创建的 Fragment 添加到这个容器中
- position:表示当前页面的位置
- 参数解析:
-
adapter.destroyItem(ViewGroup container, int position, Object object);
:从 container 中移除并销毁指定位置的 Fragment 对象- 参数解析:
- container:ViewGroup,即 ViewPager,用于从这个容器中移除 Fragment
- position:表示要销毁的页面的位置
- object:即 Fragment 对象
- 参数解析:
-
adapter.getItem(int position);
:返回指定位置的 Fragment 对象。每次需要新的 Fragment 时,ViewPager 会调用这个方法。此方法必须被重写,返回对应位置的 Fragment@Override public Fragment getItem(int position) { switch (position) { case 0: return new Fragment1(); case 1: return new Fragment2(); case 2: return new Fragment3(); default: return null; } } //调用 Fragment Item = adapter.getItem(0) //Fragment1 在 ViewPager 中的位置
- 参数解析:
- position:返回的 Fragment 在 ViewPager 中的位置
- 参数解析:
-
adapter.getCount();
:返回 Fragment 的总数量,即 ViewPager 中页面的数量。此方法必须被重写@Override public int getCount() { return 3; // 总共3个页面 }
使用环境与完整代码解析
-
FragmentPagerAdapter 主要用于 ViewPager 中管理和显示 Fragment。以下是一些典型的使用环境和场景:
经典的 Tab 界面
-
使用了 TabLayout 和 ViewPager。ViewPager 允许用户通过左右滑动来切换页面,同时 TabLayout 提供了页签来快速跳转到特定页面。用户可以通过点击不同的 tab 或者左右滑动来切换页面
-
代码示例:MainActivity 中的 ViewPager 以及 MyPagerAdapter 的设置支持左右滑动
-
创建主布局文件:
res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true"/> <androidx.viewpager.widget.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/tabLayout"/> </RelativeLayout>
-
创建fragment1布局文件:
res/layout/fragment_first.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is the first tab" android:textSize="24sp" android:layout_gravity="center"/> </FrameLayout>
-
创建fragment2布局文件:
res/layout/fragment_second.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is the second tab" android:textSize="24sp" android:layout_gravity="center"/> </FrameLayout>
-
创建fragment3布局文件:
res/layout/fragment_third.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is the third tab" android:textSize="24sp" android:layout_gravity="center"/> </FrameLayout>
-
每个 Fragment 的实现类似,只需修改显示的内容
-
FirstFragment.java
//定义了具体的视图和行为 public class FirstFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_first, container, false); } }
-
SecondFragment.java
//定义了具体的视图和行为 public class SecondFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_second, container, false); } }
-
ThirdFragment.java
//定义了具体的视图和行为 public class ThirdFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_third, container, false); } }
-
-
自定义FragmentPagerAdapter类:
MyPagerAdapter.java
public class MyPagerAdapter extends FragmentPagerAdapter { public MyPagerAdapter(FragmentManager fm) { super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); } @Override public Fragment getItem(int position) { // 根据位置返回不同的 Fragment switch (position) { case 0: return new FirstFragment(); case 1: return new SecondFragment(); case 2: return new ThirdFragment(); default: return new FirstFragment(); } } @Override public int getCount() { // 返回页数 return 3; } @Override public CharSequence getPageTitle(int position) { // 返回每个 tab 的标题 switch (position) { case 0: return "Tab 1"; case 1: return "Tab 2"; case 2: return "Tab 3"; default: return null; } } }
-
启动类
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //加载主布局文件,该布局文件定义了活动的 UI 结构。这包括 ViewPager、TabLayout(如果使用)、和其他 UI 元素 setContentView(R.layout.activity_main); //获取布局中的 ViewPager 和其他 UI 组件的引用,以便后续的操作和设置 ViewPager viewPager = findViewById(R.id.viewPager); TabLayout tabLayout = findViewById(R.id.tabLayout); // 创建适配器 MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager()); //通过适配器(FragmentPagerAdapter)与 Fragment 类关联。适配器负责创建和管理 Fragment 实例,并将这些实例添加到 ViewPager 中 //自定义的 FragmentPagerAdapter 子类中定义了如何创建和管理 Fragment 对象 viewPager.setAdapter(adapter); //将 TabLayout 绑定到 ViewPager 上,以便用户可以通过点击标签页快速切换,同时也可以通过左右滑动切换 tabLayout.setupWithViewPager(viewPager); } }
-
带有动态内容的多页面界面
-
使用了 ViewPager 来展示多个页面,每个页面展示不同的动态内容。用户可以通过左右滑动来浏览不同的页面
-
代码示例:MainActivity 中的 ViewPager 和 DynamicPagerAdapter 支持左右滑动
-
创建主布局文件:
res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true"/> <androidx.viewpager.widget.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/tabLayout"/> </RelativeLayout>
-
创建fragment布局文件:
res/layout/fragment_dynamic.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="24sp" android:layout_gravity="center"/> </FrameLayout>
-
自定义FragmentPagerAdapter类:
DynamicPagerAdapter.java
public class DynamicPagerAdapter extends FragmentPagerAdapter { private List<String> dataList; public DynamicPagerAdapter(FragmentManager fm, List<String> data) { super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); this.dataList = data; } @Override public Fragment getItem(int position) { // 获取每个 Fragment 的动态数据 String data = dataList.get(position); return DynamicFragment.newInstance(data); } @Override public int getCount() { // 返回数据项的数量 return dataList.size(); } }
-
自定义 Fragment 类:
DynamicFragment.java
public class DynamicFragment extends Fragment { private static final String ARG_DATA = "data"; // 创建新实例并传递数据 public static DynamicFragment newInstance(String data) { DynamicFragment fragment = new DynamicFragment(); Bundle args = new Bundle(); args.putString(ARG_DATA, data); fragment.setArguments(args); return fragment; } //定义了具体的视图和行为 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_dynamic, container, false); // 获取传递的数据并显示 String data = getArguments().getString(ARG_DATA); TextView textView = view.findViewById(R.id.textView); textView.setText(data); return view; } }
-
启动类
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //加载主布局文件,该布局文件定义了活动的 UI 结构。这包括 ViewPager、TabLayout(如果使用)、和其他 UI 元素 setContentView(R.layout.activity_main); //获取布局中的 ViewPager 和其他 UI 组件的引用,以便后续的操作和设置 ViewPager viewPager = findViewById(R.id.viewPager); // 模拟动态数据:提供数据源(例如 List<String> data),并将数据传递给适配器,以便动态生成页面 List<String> data = Arrays.asList("Page 1", "Page 2", "Page 3"); // 创建适配器 DynamicPagerAdapter adapter = new DynamicPagerAdapter(getSupportFragmentManager(), data); //通过适配器(FragmentPagerAdapter)与 Fragment 类关联。适配器负责创建和管理 Fragment 实例,并将这些实例添加到 ViewPager 中 //自定义的 FragmentPagerAdapter 子类中定义了如何创建和管理 Fragment 对象 viewPager.setAdapter(adapter); } }
-
复杂的内容展示
-
场景中同样使用了 ViewPager。每个页面可能包含更复杂的 UI 组件和交互,但 ViewPager 依然支持左右滑动来切换不同的页面
-
代码示例:MainActivity 中的 ViewPager 和 ComplexPagerAdapter 支持左右滑动
-
创建主布局文件:
res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true"/> <androidx.viewpager.widget.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/tabLayout"/> </RelativeLayout>
-
创建fragment布局文件:
res/layout/fragment_complex.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <TextView android:id="@+id/positionTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="24sp"/> <Button android:id="@+id/actionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Click Me" android:layout_marginTop="16dp"/> </LinearLayout>
-
自定义FragmentPagerAdapter类:
ComplexPagerAdapter.java
public class ComplexPagerAdapter extends FragmentPagerAdapter { public ComplexPagerAdapter(FragmentManager fm) { super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); } @Override public Fragment getItem(int position) { // 根据位置创建不同的 Fragment return ComplexFragment.newInstance(position); } @Override public int getCount() { // 返回页数 return 5; } }
-
自定义 Fragment 类:
ComplexFragment.java
public class ComplexFragment extends Fragment { private static final String ARG_POSITION = "position"; // 创建新实例并传递位置参数 public static ComplexFragment newInstance(int position) { ComplexFragment fragment = new ComplexFragment(); Bundle args = new Bundle(); args.putInt(ARG_POSITION, position); fragment.setArguments(args); return fragment; } //定义了具体的视图和行为 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_complex, container, false); int position = getArguments().getInt(ARG_POSITION); // 初始化视图并处理复杂内容 TextView positionTextView = view.findViewById(R.id.positionTextView); positionTextView.setText("Position: " + position); Button actionButton = view.findViewById(R.id.actionButton); actionButton.setOnClickListener(v -> { // 处理按钮点击事件 Toast.makeText(getActivity(), "Button in position " + position + " clicked!", Toast.LENGTH_SHORT).show(); }); return view; } }
-
启动类
// public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //加载主布局文件,该布局文件定义了活动的 UI 结构。这包括 ViewPager、TabLayout(如果使用)、和其他 UI 元素 setContentView(R.layout.activity_main); //获取布局中的 ViewPager 和其他 UI 组件的引用,以便后续的操作和设置 ViewPager viewPager = findViewById(R.id.viewPager); // 创建适配器 ComplexPagerAdapter adapter = new ComplexPagerAdapter(getSupportFragmentManager()); //通过适配器(FragmentPagerAdapter)与 Fragment 类关联。适配器负责创建和管理 Fragment 实例,并将这些实例添加到 ViewPager 中 //自定义的 FragmentPagerAdapter 子类中定义了如何创建和管理 Fragment 对象 viewPager.setAdapter(adapter); } }
-
-