FragmentStatePagerAdapter的getFragment(int position) 导致的NullPointerException

本文介绍了解决ViewPager结合FragmentStatePagerAdapter在特定条件下出现的空指针异常问题。提供了三种解决方案,包括更换适配器类型、重写saveState方法返回null及在restoreState方法中捕获异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

totalList.add(TaskFragment.newInstance(TASK_TYPE_DAILY));
        totalList.add(TaskFragment.newInstance(TASK_TYPE_GROW));
        totalList.add(TaskFragment.newInstance(TASK_TYPE_CYCLE));

        viewpagerTask.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager()) {
            @Override
            public int getCount() {
                return totalList.size();
            }

            @Override
            public Fragment getItem(int position) {
                return totalList.get(position);
            }

            @Override
            public CharSequence getPageTitle(int position) {
                if (position == 0) {
                    return "日常任务";
                } else if (position == 1) {
                    return "成长任务";
                } else {
                    return "周期任务";
                }
            }
        });
        viewpagerTask.setOffscreenPageLimit(3);

我的TaskActivity中有一个viewpager,装载3个fragment碎片:

发现偶尔有时候会出现以下崩溃log:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sina.book/com.sina.book.ui.activity.bookstore.TaskActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.util.SparseArray.get(int)' on a null object reference
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3000)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3078)
	at android.app.ActivityThread.-wrap11(Unknown Source:0)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
	at android.os.Handler.dispatchMessage(Handler.java:106)
	at android.os.Looper.loop(Looper.java:187)
	at android.app.ActivityThread.main(ActivityThread.java:7025)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:514)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:888)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.util.SparseArray.get(int)' on a null object reference
	at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:905)
	at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:216)
	at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1455)
	at android.view.View.dispatchRestoreInstanceState(View.java:17993)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3859)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3865)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3865)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3865)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3865)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3865)
	at android.view.View.restoreHierarchyState(View.java:17971)
	at com.android.internal.policy.PhoneWindow.restoreHierarchyState(PhoneWindow.java:2198)
	at android.app.Activity.onRestoreInstanceState(Activity.java:1173)
	at android.app.Activity.performRestoreInstanceState(Activity.java:1128)
	at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1260)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2973)
	... 9 more
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.util.SparseArray.get(int)' on a null object reference
	at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:905)
	at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:216)
	at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1455)
	at android.view.View.dispatchRestoreInstanceState(View.java:17993)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3859)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3865)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3865)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3865)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3865)
	at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3865)
	at android.view.View.restoreHierarchyState(View.java:17971)
	at com.android.internal.policy.PhoneWindow.restoreHierarchyState(PhoneWindow.java:2198)
	at android.app.Activity.onRestoreInstanceState(Activity.java:1173)
	at android.app.Activity.performRestoreInstanceState(Activity.java:1128)
	at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1260)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2973)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3078)
	at android.app.ActivityThread.-wrap11(Unknown Source:0)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
	at android.os.Handler.dispatchMessage(Handler.java:106)
	at android.os.Looper.loop(Looper.java:187)
	at android.app.ActivityThread.main(ActivityThread.java:7025)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:514)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:888)

然后这个bug不是必现,所以复现起来有些麻烦。幸好网上大牛还是厉害,找到了复习办法:

我使用更高版本(4.1)设备并按照以下步骤操作:
1.转到设置 – >开发者选项.
2.单击“不要保留活动”选项.

怎么解决呢?

经过一番Google,得到一些解决办法,有两种:

第一种:讲FragmentStatePagerAdapter改为FragmentPagerAdapter;

第二种:重写FragmentStatePagerAdapter的saveState()方法,直接return null;

@Override
public Parcelable saveState() {
    // Do Nothing
    return null;
}

第三种:重写FragmentStatePagerAdapter的restoreState方法,捕获异常



            @Override
            public void restoreState(Parcelable state, ClassLoader loader) {
                try {
                    super.restoreState(state, loader);
                } catch (NullPointerException e) {

                }
            }

其实,第二种方法屏蔽了FragmentStatePagerAdapter的保存数据的特性之后,就跟第一种方法没有区别了!

说改就改,过几天看看测试的妹子会不会找过来!

package com.luck.picture.lib; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Parcelable; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.luck.picture.lib.config.PictureConfig; import com.luck.picture.lib.config.PictureMimeType; import com.luck.picture.lib.entity.LocalMedia; import com.luck.picture.lib.style.PictureParameterStyle; import com.luck.picture.lib.tools.DoubleUtils; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; /** * @author:luck * @date:2017-5-24 22:30 * @describe:PictureSelector */ public final class PictureSelector { private final WeakReference<Activity> mActivity; private final WeakReference<Fragment> mFragment; private PictureSelector(Activity activity) { this(activity, null); } private PictureSelector(Fragment fragment) { this(fragment.getActivity(), fragment); } private PictureSelector(Activity activity, Fragment fragment) { mActivity = new WeakReference<>(activity); mFragment = new WeakReference<>(fragment); } /** * Start PictureSelector for Activity. * * @param activity * @return PictureSelector instance. */ public static PictureSelector create(Activity activity) { return new PictureSelector(activity); } /** * Start PictureSelector for Fragment. * * @param fragment * @return PictureSelector instance. */ public static PictureSelector create(Fragment fragment) { return new PictureSelector(fragment); } /** * @param chooseMode Select the type of picture you want,all or Picture or Video . * @return LocalMedia PictureSelectionModel * Use {@link PictureMimeType.ofAll(),ofImage(),ofVideo(),ofAudio()}. */ public PictureSelectionModel openGallery(int chooseMode) { return new PictureSelectionModel(this, chooseMode); } /** * @param chooseMode Select the type of picture you want,Picture or Video. * @return LocalMedia PictureSelectionModel * Use {@link PictureMimeType.ofImage(),ofVideo()}. */ public PictureSelectionModel openCamera(int chooseMode) { return new PictureSelectionModel(this, chooseMode, true); } /** * 外部预览时设置样式 * * @param themeStyle * @return */ public PictureSelectionModel themeStyle(int themeStyle) { return new PictureSelectionModel(this, PictureMimeType.ofImage()) .theme(themeStyle); } /** * 外部预览时动态代码设置样式 * * @param style * @return */ public PictureSelectionModel setPictureStyle(PictureParameterStyle style) { return new PictureSelectionModel(this, PictureMimeType.ofImage()) .setPictureStyle(style); } /** * @param data * @return Selector Multiple LocalMedia */ public static List<LocalMedia> obtainMultipleResult(Intent data) { if (data != null) { List<LocalMedia> result = data.getParcelableArrayListExtra(PictureConfig.EXTRA_RESULT_SELECTION); return result == null ? new ArrayList<>() : result; } return new ArrayList<>(); } /** * @param data * @return Put image Intent Data */ public static Intent putIntentResult(List<LocalMedia> data) { return new Intent().putParcelableArrayListExtra(PictureConfig.EXTRA_RESULT_SELECTION, (ArrayList<? extends Parcelable>) data); } /** * @param bundle * @return get Selector LocalMedia */ public static List<LocalMedia> obtainSelectorList(Bundle bundle) { if (bundle != null) { return bundle.getParcelableArrayList(PictureConfig.EXTRA_SELECT_LIST); } return null; } /** * @param selectedImages * @return put Selector LocalMedia */ public static void saveSelectorList(Bundle outState, List<LocalMedia> selectedImages) { outState.putParcelableArrayList(PictureConfig.EXTRA_SELECT_LIST, (ArrayList<? extends Parcelable>) selectedImages); } /** * set preview image * * @param position * @param medias */ public void externalPicturePreview(int position, List<LocalMedia> medias, int enterAnimation) { if (!DoubleUtils.isFastDoubleClick()) { if (getActivity() != null) { Intent intent = new Intent(getActivity(), PictureExternalPreviewActivity.class); intent.putParcelableArrayListExtra(PictureConfig.EXTRA_PREVIEW_SELECT_LIST, (ArrayList<? extends Parcelable>) medias); intent.putExtra(PictureConfig.EXTRA_POSITION, position); getActivity().startActivity(intent); getActivity().overridePendingTransition(enterAnimation != 0 ? enterAnimation : R.anim.picture_anim_enter, R.anim.picture_anim_fade_in); } else { throw new NullPointerException("Starting the PictureSelector Activity cannot be empty "); } } } /** * set preview image * * @param position * @param medias * @param directory_path */ public void externalPicturePreview(int position, String directory_path, List<LocalMedia> medias, int enterAnimation) { if (!DoubleUtils.isFastDoubleClick()) { if (getActivity() != null) { Intent intent = new Intent(getActivity(), PictureExternalPreviewActivity.class); intent.putParcelableArrayListExtra(PictureConfig.EXTRA_PREVIEW_SELECT_LIST, (ArrayList<? extends Parcelable>) medias); intent.putExtra(PictureConfig.EXTRA_POSITION, position); intent.putExtra(PictureConfig.EXTRA_DIRECTORY_PATH, directory_path); getActivity().startActivity(intent); getActivity().overridePendingTransition(enterAnimation != 0 ? enterAnimation : R.anim.picture_anim_enter, R.anim.picture_anim_fade_in); } else { throw new NullPointerException("Starting the PictureSelector Activity cannot be empty "); } } } /** * set preview video * * @param path */ public void externalPictureVideo(String path) { if (!DoubleUtils.isFastDoubleClick()) { if (getActivity() != null) { Intent intent = new Intent(getActivity(), PictureVideoPlayActivity.class); intent.putExtra(PictureConfig.EXTRA_VIDEO_PATH, path); intent.putExtra(PictureConfig.EXTRA_PREVIEW_VIDEO, true); getActivity().startActivity(intent); } else { throw new NullPointerException("Starting the PictureSelector Activity cannot be empty "); } } } /** * set preview audio * * @param path */ public void externalPictureAudio(String path) { if (!DoubleUtils.isFastDoubleClick()) { if (getActivity() != null) { Intent intent = new Intent(getActivity(), PicturePlayAudioActivity.class); intent.putExtra(PictureConfig.EXTRA_AUDIO_PATH, path); getActivity().startActivity(intent); getActivity().overridePendingTransition(R.anim.picture_anim_enter, 0); } else { throw new NullPointerException("Starting the PictureSelector Activity cannot be empty "); } } } /** * @return Activity. */ @Nullable Activity getActivity() { return mActivity.get(); } /** * @return Fragment. */ @Nullable Fragment getFragment() { return mFragment != null ? mFragment.get() : null; } } 有没有方法控制是否拍照或者拍摄视频保存到相册
06-04
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值