【发布时间】:2017-07-08 09:36:06
【问题描述】:
我想使用 ViewPager 创建一个视频列表。我必须知道寻呼机项目何时可见,何时不可见。
我使用 VideoListAdapter 为 ViewPager 扩展 FragmentStatePagerAdapter。
我使用 Fragment 方法 setUserVisibleHint 来触发视频开始或暂停。
但是有一个问题,ViewPager的位置0的Fragment抛出了NullPointerException。然后我为 Fragment 的相关方法打印日志。
我进入 VideoListActivity 的日志:
07-08 17:06:50.264 E/lemon: startUpdate
07-08 17:06:50.264 E/lemon: instantiateItem 0
07-08 17:06:50.264 E/lemon: getItem 0
07-08 17:06:50.264 E/lemon: setUserVisibleHint 0 isVisibleToUser false
07-08 17:06:50.264 E/lemon: instantiateItem 1
07-08 17:06:50.264 E/lemon: getItem 1
07-08 17:06:50.264 E/lemon: setUserVisibleHint 0 isVisibleToUser false
07-08 17:06:50.264 E/lemon: setPrimaryItem 0
07-08 17:06:50.264 E/lemon: setUserVisibleHint 0 isVisibleToUser true
07-08 17:06:50.264 E/lemon: finishUpdate
07-08 17:06:50.265 E/lemon: onAttach 0
07-08 17:06:50.265 E/lemon: onAttach 1
07-08 17:06:50.265 E/lemon: onCreateView 0
07-08 17:06:50.267 E/lemon: onstart 0
07-08 17:06:50.267 E/lemon: onCreateView 1
07-08 17:06:50.269 E/lemon: onstart 1
07-08 17:06:50.270 E/lemon: startUpdate
07-08 17:06:50.270 E/lemon: setPrimaryItem 0
07-08 17:06:50.270 E/lemon: finishUpdate
07-08 17:06:50.297 E/lemon: startUpdate
07-08 17:06:50.297 E/lemon: setPrimaryItem 0
07-08 17:06:50.297 E/lemon: finishUpdate
07-08 17:06:50.297 E/lemon: startUpdate
07-08 17:06:50.297 E/lemon: setPrimaryItem 0
07-08 17:06:50.297 E/lemon: finishUpdate
07-08 17:06:50.703 E/lemon: startUpdate
07-08 17:06:50.703 E/lemon: setPrimaryItem 0
07-08 17:06:50.703 E/lemon: finishUpdate
07-08 17:06:50.704 E/lemon: startUpdate
07-08 17:06:50.704 E/lemon: setPrimaryItem 0
07-08 17:06:50.704 E/lemon: finishUpdate
我滚动到位置 1 的日志:
07-08 17:09:41.154 E/lemon: startUpdate
07-08 17:09:41.154 E/lemon: setPrimaryItem 0
07-08 17:09:41.154 E/lemon: finishUpdate
07-08 17:09:41.966 E/lemon: startUpdate
07-08 17:09:41.966 E/lemon: instantiateItem 2
07-08 17:09:41.967 E/lemon: getItem 2
07-08 17:09:41.967 E/lemon: setUserVisibleHint 0 isVisibleToUser false
07-08 17:09:41.967 E/lemon: setPrimaryItem 1
07-08 17:09:41.967 E/lemon: setUserVisibleHint 0 isVisibleToUser false
07-08 17:09:41.967 E/lemon: setUserVisibleHint 1 isVisibleToUser true
07-08 17:09:41.967 E/lemon: finishUpdate
07-08 17:09:41.968 E/lemon: onAttach 2
07-08 17:09:41.968 E/lemon: onCreateView 2
07-08 17:09:41.971 E/lemon: onstart 2
07-08 17:09:41.971 E/lemon: startUpdate
07-08 17:09:41.971 E/lemon: setPrimaryItem 1
07-08 17:09:41.971 E/lemon: finishUpdate
07-08 17:09:41.972 E/lemon: startUpdate
07-08 17:09:41.972 E/lemon: setPrimaryItem 1
07-08 17:09:41.972 E/lemon: finishUpdate
我分析了这些日志,发现位置0的fragment先调用setUserVisibleHint(true)然后调用onAttach(),但是位置1的fragment先调用onAttach(),后调用setUserVisibleHint(true)。
所以我在 Fragment 中编写了一个 onTrigger() 方法,同时在 onAttach() 和 setUserVisibleHint(true) 中调用,但是失败了。然后我调试我的代码,它表明在 onAttach() 中调用 onTrigger 时 onTrigger() 中的 isAdded() 返回 false。
所以这里有任何建议让我知道何时触发我的视频开始。非常感谢。
public class FullScreenVideoFragment extends Fragment {
private FragmentFullScreenVideoBinding binding;
int colorRes;
int position;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.e("lemon", "onCreateView " + position);
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_full_screen_video, container, false);
setView();
return binding.getRoot();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void setBgAndPosition(int position, int colorRes) {
this.position = position;
this.colorRes = colorRes;
}
@Override
public void onAttach(Context context) {
Log.e("lemon", "onAttach " + position);
super.onAttach(context);
onTriger();
}
@Override
public void onDetach() {
Log.e("lemon", "onDetach " + position);
super.onDetach();
}
@Override
public void onAttachFragment(Fragment childFragment) {
Log.e("lemon", "onAttachFragment " + position);
super.onAttachFragment(childFragment);
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
Log.e("lemon", "setUserVisibleHint " + position + " isVisibleToUser " + isVisibleToUser);
super.setUserVisibleHint(isVisibleToUser);
onTriger();
}
private void setView() {
binding.getRoot().setBackgroundResource(colorRes);
binding.position.setText(String.valueOf(position));
}
private void onTriger() {
if (!isVisible()) return;
binding.position.setText(position + " start");
}
}
public class VideoListAdapter extends FragmentStatePagerAdapter {
private LinkedList<FullScreenVideoFragment> fragmentCaches;
private int[] colors = new int[]{android.graphics.Color.RED, android.graphics.Color.BLUE, android.graphics.Color.GREEN};
public VideoListAdapter(FragmentManager fm) {
super(fm);
fragmentCaches = new LinkedList<>();
}
@Override
public Fragment getItem(int position) {
Log.e("lemon", "getItem " + position);
FullScreenVideoFragment fragment = generateItem();
return fragment;
}
@Override
public int getCount() {
return 10;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
Log.e("lemon", "destroyItem " + position);
super.destroyItem(container, position, object);
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
Log.e("lemon", "setPrimaryItem " + position);
super.setPrimaryItem(container, position, object);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Log.e("lemon", "instantiateItem " + position);
FullScreenVideoFragment fragment = (FullScreenVideoFragment) super.instantiateItem(container, position);
fragment.setBgAndPosition(position, colors[position % 3]);
return fragment;
}
@Override
public void startUpdate(ViewGroup container) {
Log.e("lemon", "startUpdate");
super.startUpdate(container);
}
@Override
public void finishUpdate(ViewGroup container) {
Log.e("lemon", "finishUpdate");
super.finishUpdate(container);
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
Log.e("lemon", "restoreState");
super.restoreState(state, loader);
}
@Override
public Parcelable saveState() {
Log.e("lemon", "saveState");
return super.saveState();
}
private FullScreenVideoFragment generateItem() {
FullScreenVideoFragment neededFragment = null;
if (!fragmentCaches.isEmpty()) {
neededFragment = fragmentCaches.get(0);
fragmentCaches.remove(0);
return neededFragment;
}
neededFragment = new FullScreenVideoFragment();
return neededFragment;
}
}
片段xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data></data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/position"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@color/account_name_color"/>
</RelativeLayout>
</layout>
【问题讨论】:
标签: android lifecycle fragmentstatepageradapter