静态注册是在XML文件中直接添加fragment节点,而动态注册延迟至代码执行时才动态添加碎片,动态生 成的碎片基本给翻页视图使用,要知道ViewPager和Fragment可是一对好搭档。
如果结合使用碎片,翻页视图的适配器就要改用碎片适配器 FragmentPagerAdapter。与翻页适配器相比,碎片适配器增加了getItem方法用于获取指定位置的碎 片,同时去掉了isViewFromObject、instantiateItem、destroyItem三个方法,用起来更加容易。
案例中图片来源
布局文件
fragmen_dynamic.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <ImageView android:id="@+id/iv_pic" android:layout_width="match_parent" android:layout_height="360dp" android:scaleType="fitCenter" /> <TextView android:id="@+id/tv_desc" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="left" android:textColor="@color/black" android:textSize="17sp" /> </LinearLayout>
activity_fragmen_dynamic.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"> <androidx.viewpager.widget.ViewPager android:id="@+id/vp_content" android:layout_width="match_parent" android:layout_height="wrap_content"> <androidx.viewpager.widget.PagerTabStrip android:id="@+id/pts_tab" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </androidx.viewpager.widget.ViewPager> </LinearLayout>
碎片程序
DynamicFragment.java
import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import com.kcs.highcontrol.R; public class DynamicFragment extends Fragment { private static final String TAG = "fragment"; public static DynamicFragment newInstance(int position, int image_id, String desc) { DynamicFragment fragment = new DynamicFragment(); // 把参数打包,传入fragment中 Bundle args = new Bundle(); args.putInt("position", position); args.putInt("image_id", image_id); args.putString("desc", desc); fragment.setArguments(args); return fragment; } /** * 从包裹取出位置序号 * @return */ private int getPosition(){ return getArguments().getInt("position", 0); } @Override public void onAttach(@NonNull Context context) { // 把碎片贴到页面上 super.onAttach(context); Log.d(TAG, "fragment onAttach position=" + getPosition()); } @Override public void onCreate(Bundle savedInstanceState) { // 页面创建 super.onCreate(savedInstanceState); Log.d(TAG, "fragment onCreate position=" + getPosition()); } /** * 创建碎片视图 */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // 根据布局文件fragment_dynamic.xml生成视图对象 View view = inflater.inflate(R.layout.fragment_dynamic, container, false); Bundle arguments = getArguments(); if (arguments != null){ ImageView iv_pic = view.findViewById(R.id.iv_pic); TextView tv_desc = view.findViewById(R.id.tv_desc); iv_pic.setImageResource(arguments.getInt("image_id",R.drawable.huawei)); tv_desc.setText(arguments.getString("desc")); } Log.d(TAG, "fragment onCreateView position=" + getPosition()); return view; } @Override public void onActivityCreated(Bundle savedInstanceState) { //在活动页面创建之后 super.onActivityCreated(savedInstanceState); Log.d(TAG, "fragment onActivityCreated position=" + getPosition()); } @Override public void onStart() { // 页面启动 super.onStart(); Log.d(TAG, "fragment onStart position=" + getPosition()); } @Override public void onResume() { // 页面恢复 super.onResume(); Log.d(TAG, "fragment onResume position=" + getPosition()); } @Override public void onPause() { // 页面暂停 super.onPause(); Log.d(TAG, "fragment onPause position=" + getPosition()); } @Override public void onStop() { // 页面停止 super.onStop(); Log.d(TAG, "fragment onStop position=" + getPosition()); } @Override public void onDestroyView() { // 销毁碎片视图 super.onDestroyView(); Log.d(TAG, "fragment onDestroyView position=" + getPosition()); } @Override public void onDestroy() { // 页面销毁 super.onDestroy(); Log.d(TAG, "fragment onDestroy position=" + getPosition()); } @Override public void onDetach() { // 把碎片从页面撕下来 super.onDetach(); Log.d(TAG, "fragment onDetach position=" + getPosition()); } }
适配器
MobilePagerAdapter.java
import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; import com.kcs.highcontrol.fragment.DynamicFragment; import com.kcs.highcontrol.pojo.GoodsInfo; import java.util.List; public class MobilePagerAdapter extends FragmentPagerAdapter { private final List<GoodsInfo> mGoodsList; public MobilePagerAdapter(@NonNull FragmentManager fm, List<GoodsInfo> goodsList) { // 会将当前fragment设置为Resume的状态,把上个fragment设置成Start的状态。 // 从而可以通过fragment的onResume()来懒加载数据。 super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); this.mGoodsList = goodsList; } @NonNull @Override public Fragment getItem(int position) { GoodsInfo info = mGoodsList.get(position); return DynamicFragment.newInstance(position, info.pic, info.description); } @Override public int getCount() { return mGoodsList.size(); } @Nullable @Override public CharSequence getPageTitle(int position) { return mGoodsList.get(position).name; } }
适配器代码在getItem方法中不调用碎片的构造方法,却调用了newInstance方法,目的是给碎片 对象传递参数信息。由newInstance方法内部先调用构造方法创建碎片对象,再调用setArguments方法 塞进请求参数,然后在onCreateView中调用getArguments方法才能取出请求参数。
主程序
活动页面展示翻页视图及其搭配的碎片适配器
import android.graphics.Color; import android.os.Bundle; import android.util.TypedValue; import androidx.appcompat.app.AppCompatActivity; import androidx.viewpager.widget.PagerTabStrip; import androidx.viewpager.widget.ViewPager; import com.kcs.highcontrol.adapter.MobilePagerAdapter; import com.kcs.highcontrol.pojo.GoodsInfo; import java.util.ArrayList; public class FragmentDynamicActivity extends AppCompatActivity { private ArrayList<GoodsInfo> mGoodsList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fragment_dynamic); initPagerStrip(); initViewPager(); } /** * 初始化翻页标签栏 */ private void initPagerStrip() { PagerTabStrip pts_tab = findViewById(R.id.pts_tab); // 设置翻页标签栏的文本大小 pts_tab.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20); pts_tab.setTextColor(Color.BLACK); } /** * 初始化翻页视图 */ private void initViewPager() { ViewPager vp_content = findViewById(R.id.vp_content); mGoodsList = GoodsInfo.getDefaultList(); MobilePagerAdapter adapter = new MobilePagerAdapter(getSupportFragmentManager(), mGoodsList); vp_content.setAdapter(adapter); } }
日志效果
启动时的执行的生命周期
翻页执行的周期
日志总结
动态注册时,碎片的onCreate方法在活动的onCreate方法之后,其余方法的先后顺序与静态注册 时保持一致。
注意onActivityCreated方法,无论是静态注册还是动态注册,该方法都在活动的onCreate方法之 后,可见该方法的确在页面创建之后才调用。
最重要的一点,进入第一个碎片之际,实际只加载了第一页和第二页,并没有加载所有碎片页,这 正是碎片动态注册的优点。无论当前位于哪一页,系统都只会加载当前页及相邻的左右两页,总共加载 不超过3页。一旦发生页面切换,相邻页面就被加载,非相邻页面就被回收。这么做的好处是节省了宝贵 的系统资源,只有用户正在浏览与将要浏览的碎片页才会加载,避免所有碎片页一起加载造成资源浪 费,后者正是普通翻页视图的缺点。