huburt-Hu / NewbieGuide

Android 快速实现新手引导层的库,通过简洁链式调用,一行代码实现引导层的显示
Apache License 2.0
3.56k stars 521 forks source link

此null异常以及发生多次,希望优化(以更新到2.4.2版本了) #149

Open mouse09 opened 5 years ago

mouse09 commented 5 years ago

java.lang.NullPointerException:Attempt to invoke interface method 'void com.app.hubert.guide.lifecycle.FragmentLifecycle.onStart()' on a null object reference

com.app.hubert.guide.lifecycle.V4ListenerFragment.onStart(V4ListenerFragment.java:25) android.support.v4.app.Fragment.performStart(Fragment.java:2372) android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1467)

shuheming commented 5 years ago

I hope so!

jhwsx commented 4 years ago

最新的版本2.4.4还有这个异常吗?

hushenghao commented 4 years ago

复现步骤: 蒙版显示状态下,放到后台后因系统资源限制销毁了Activity(可以打开不保留活动快速复现),再次打开蒙版Activity即可复现。

原因: 重新打开已经被销毁的Activity时,系统会对Activity的状态进行恢复,包括Fragment的状态,此时V4ListenerFragment/ListenerFragment实例是由系统创建的,不会调用setFragmentLifecycle方法,所以mFragmentLifecycle为null,到onStart生命周期后就会抛出空指针异常。

解决方案:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    // 手动移除监听Fragment
    val listenerFragment = childFragmentManager.findFragmentByTag("listener_fragment") as? V4ListenerFragment
    if (listenerFragment != null) {
        // 临时设置非空回调
        listenerFragment.setFragmentLifecycle(object : FragmentLifecycleAdapter() {})
        childFragmentManager.beginTransaction()
                .remove(listenerFragment)
                .commitNow()
    }

    // 显示蒙版
    NewbieGuide.with(this)
            .setLabel(SPCacheHelp.SP_GUIDE_MY_VIDEO)
            .alwaysShow(true)
            .addGuidePage(GuidePage.newInstance()
                    .setLayoutRes(R.layout.layout_my_video_guide)
                    .setEverywhereCancelable(true))
            .show()
}

源码修复方案: 判空即可,因为系统回收Activity的时机是不确定。onSaveInstanceState方法也没有参考价值,因为onStop之前就会调用onSaveInstanceState方法(不包含老版本系统)。

Warkey1991 commented 2 years ago

2.4.4 版本看源码已经添加了判空逻辑。