静态注册是在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页。一旦发生页面切换,相邻页面就被加载,非相邻页面就被回收。这么做的好处是节省了宝贵 的系统资源,只有用户正在浏览与将要浏览的碎片页才会加载,避免所有碎片页一起加载造成资源浪 费,后者正是普通翻页视图的缺点。