ViewPager(二),android 移动应用开发教程
解析:当直接使用 PagerAdapter 时,必须重写 destroyItem 方法,FragmentPagerAdapter 已经为我们写好 destroyItem 的实现,源码如下:
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
Fragment fragment = (Fragment) object;
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
" v=" + (fragment.getView()));
mCurTransaction.detach(fragment);
if (fragment == mCurrentPrimaryItem) {
mCurrentPrimaryItem = null;
}
}
其核心代码是:
mCurTransaction.detach(fragment);
对于不再需要的 fragment,FragmentPagerAdapter 会选择调用事务的 detach()方法来处理它,而非 remove()方法。也就是说, FragmentPagerAdapter 只是销毁了 fragment 的视图, fragment 实例还保留在 FragmentManager 中。因此,FragmentPagerAdapter 创建的 fragment 永远不会被销毁。
当页面需要刷新时,选择 FragmentStatePagerAdapter;
解析:
如果使用 FragmentPagerAdapter,Fragment 对象一般不会被销毁的,这时需要修改 ViewPager 适配器中的传值,再调用以下方法刷新数据
myPagerAdapter2.notifyDataSetChanged();
但是,如果 ViewPager 页面比较多时,内存中会有大量的 Fragment 对象无法释放,浪费了内存。另外,由于 ViewPager 的自身特性,在内存中默认存在 3 个页面,其余页面会自动销毁,这样导致的情况是:ViewPager 页面销毁了,但是对应的 Fr
agment 对象没有被销毁,我认为这是一个严重的内存泄漏现象。
如果使用 FragmentStatePagerAdapter 的话,当 ViewPager 页面被销毁时,Fragment 对象也会被销毁,就不存在这样的内存泄漏问题。
【基本代码实现】
MyPagerAdapter2.java
public class MyPagerAdapter2 extends FragmentStatePagerAdapter {
private Context mContext;
private List<MyPagerFragment> myPagerFragmentList;
public MyPagerAdapter2(Context context , List<MyPagerFragment> list, @NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
mContext = context;
myPagerFragmentList = list;
}
@Override
public int getCount() {
return myPagerFragmentList.size();
}
@NonNull
@Override
public Fragment getItem(int position) {
return myPagerFragmentList.get(position);
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
super.destroyItem(container, position, object);
}
}
MyPagerFragment.java
public class MyPagerFragment extends Fragment {
String mContent;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mContent = (String) getArguments().get("content");
View view = inflater.inflate(R.layout.item_base, container, false) ;
TextView textView = (TextView) view.findViewById(R.id.tv);
textView.setText(mContent);
return view;
}
}
item_base.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="@+id/tv"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/ll_shape"
android:textColor="#000000"
android:gravity="center"
评论