-
数据问题
看了看官方给的例子是用一个viewmodel
只不过这个viewmodel的owner是viewPager里的每个fragment,
也就是说有3个fragment就有3个不同的viewmodel
可以在fragment创建的时候根据index来获得不同的viewmodel
如:
对于viewpager的适配器
public class DetailsPagerAdapter extends FragmentPagerAdapter {
long status_id;
private static final String[] TAB_TITLES = new String[]{"点赞","评论","转发"};
public DetailsPagerAdapter(@NonNull FragmentManager fm, int behavior, long id) { // 因为需要传参所以这里改了下
super(fm, behavior);
this.status_id = id;
}
@Override
public Fragment getItem(int position) {
// 这里返回创建的fragment,创建方式在PlaceholderFragment里写
return PlaceholderFragment.newInstance(position + 1,status_id);
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return TAB_TITLES[position];
}
@Override
public int getCount() {
return TAB_TITLES.length;
}
}
PlaceholderFragment中使用自己的argument来暂存分辨fragment的index和其他数据(比如id):
fragment的创建函数,在创建的时候把数据和index放入自身argument
public static PlaceholderFragment newInstance(int index, long id) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle bundle = new Bundle();
bundle.putInt(ARG_SECTION_NUMBER, index);
bundle.putLong(ARG_ID, id);
fragment.setArguments(bundle);
return fragment;
}
fragment 初始化的时候,从自身argument读取index和数据,用index判断自己是哪个fragment,并且把该index作为标识传入自己拥有的viewmodel。
- 注意,这里因为viewmodel的所有者为viewpager中的fragment,所以有多少个fragment就有多少个不同的viewmodel,当然生命周期也是绑定的
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
id = getArguments().getLong(ARG_ID);
commentViewModel = new ViewModelProvider(this).get(CommentViewModel.class);
int index;
if (getArguments() != null) {
index = getArguments().getInt(ARG_SECTION_NUMBER);
}else {
index = 1;
}
commentViewModel.setIndex(index);
}
Viewmodel中就主要放一个index和需要的数据,比如我这的数据就是commentListLive
public class CommentViewModel extends ViewModel {
private MutableLiveData<Integer> mIndex = new MutableLiveData<>();
private MutableLiveData<List<Comment>> commentListLive;
public CommentViewModel() {
if (commentListLive == null){
commentListLive = new MutableLiveData<List<Comment>>();
}
commentListLive = new MutableLiveData<List<Comment>>();
}
public MutableLiveData<List<Comment>> getCommentListLive() {
return commentListLive;
}
void setIndex(int index) {
mIndex.setValue(index);
}
}
-
网络请求问题
因为在viewPager中需要根据页面需要请求网络,而他自带左右1页的默认预加载setOffscreenPageLimit()
更改,但是看了看源码也不能设为1以下;
查了查可以用fragment中的setUserVisibleHint(boolean isVisibleToUser)
处理网络数据,这个方法用于判断当前页面是否可见,但是该方法被废弃;
换个思路:
比如这里我有3个fragment,从左到右是1,2,3
初始进来会自动缓存一个,所以创建了1和2。
可以看出当fragment显示的时候才会触发onResume
而不显示了就触发onPause
05-19 08:59:38.601 319-319/com.nanmu.vbo I/fragment: onCreate1
05-19 08:59:38.601 319-319/com.nanmu.vbo I/fragment: onCreate2
05-19 08:59:38.601 319-319/com.nanmu.vbo I/fragment: onCreateView1
05-19 08:59:38.602 319-319/com.nanmu.vbo I/fragment: onCreateView2
05-19 08:59:38.602 319-319/com.nanmu.vbo I/fragment: onResume1
// -------------点击切换到2号fragment
05-19 08:59:44.966 319-319/com.nanmu.vbo I/fragment: onCreate3
05-19 08:59:44.966 319-319/com.nanmu.vbo I/fragment: onCreateView3
05-19 08:59:44.967 319-319/com.nanmu.vbo I/fragment: onPause1
05-19 08:59:44.967 319-319/com.nanmu.vbo I/fragment: onResume2
// --------------点击切换到3号fragment
05-19 09:02:05.498 319-319/com.nanmu.vbo I/fragment: onPause2
05-19 09:02:05.498 319-319/com.nanmu.vbo I/fragment: onResume3
答案显而易见了,直接把网络请求放在onResume就行,然后把observer丢在onCreateView
-
子Fragment销毁和不销毁的问题
取决于adapter
继承自FragmentStatePagerAdapter
的话子fragment会随父fragment重建
而继承自FragmentPagerAdapter
的子fragment不重建
但是又有新的问题,子fragment不走destory,导致每次读取都会新建更多的子fragment
emmm,想了想这个页面还挺常用,最终决定用FragmentPagerAdapter
,然后方法都写onresume里好了
发现问题了
嵌套fragment中的fragmentManager用getChildFragmentManager()
不能用requireActivity().getSupportFragmentManager()!!!