When I run app and use it no crash. BottomSheetBehavior works correctly. But if I return to app after a long time pause in background, it crashing with null point exception when try to cast view.parent as View in order to find View with BottomSheetBehavior.
Why fragment don't have parent after pause? How to fix it?
I tried to do binding.root.parent as View and other requireActivity().findViewById(R.id.fragment_sheet_container). But the crash with same case continuous.
@AndroidEntryPoint
class ToolboxSheetFragment : Fragment(R.layout.fragment_toolbox_sheet) {
private lateinit var binding: FragmentToolboxSheetBinding
private lateinit var behavior: BottomSheetBehavior<View>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentToolboxSheetBinding.bind(view)
behavior = BottomSheetBehavior.from(
view.parent as View // null cannot be cast to non-null type android.view.View
)
}
The parent of fragment is main activity with the next layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.MainActivity">
// ...
<androidx.fragment.app.FragmentContainerView
android:id="@ id/fragment_sheet_container"
android:name=".view.fragment.ToolboxSheetFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:behavior_hideable="false"
app:behavior_peekHeight="?actionBarSize"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
tools:layout="@layout/fragment_toolbox_sheet" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
java.lang.RuntimeException: Unable to start activity ComponentInfo{
.view.MainActivity}: java.lang.NullPointerException: null cannot be cast to non-null type android.view.View
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2792)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2870)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1601)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:172)
at android.app.ActivityThread.main(ActivityThread.java:6590)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.NullPointerException: null cannot be cast to non-null type android.view.View
at .view.fragment.ToolboxSheetFragment.onViewCreated(ToolboxSheetFragment.kt:46)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3128)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:552)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1424)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2968)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2886)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:263)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:351)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1335)
at android.app.Activity.performStart(Activity.java:7043)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2755)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2870)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1601)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:172)
at android.app.ActivityThread.main(ActivityThread.java:6590)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
CodePudding user response:
It would be better if I could get full project. But I am suggesting couple of ways here:
Way 1:
How about keeping behavior inside activity class. instantiate it onCreate(). And use it from ToolboxSheetFragment like this.
class MainActivity : BaseActivity() {
var behavior: BottomSheetBehavior? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
behavior = BottomSheetBehavior.from(R.id.sheet_id)
}
}
Then from ToolboxSheetFragment
class ToolboxSheetFragment : Fragment(R.layout.fragment_toolbox_sheet) {
private lateinit var binding: FragmentToolboxSheetBinding
var behavior: BottomSheetBehavior? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentToolboxSheetBinding.bind(view)
behavior = (requireActivity() as MainActivity).behavior
}
Way 2:
Using addOnAttachStateChangeListener on ToolboxSheetFragment:
@AndroidEntryPoint
class ToolboxSheetFragment : Fragment(R.layout.fragment_toolbox_sheet) {
private lateinit var binding: FragmentToolboxSheetBinding
private lateinit var behavior: BottomSheetBehavior<View>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View?) {
if(v!=null){
binding = FragmentToolboxSheetBinding.bind(v)
behavior = BottomSheetBehavior.from(
v.parent as View
)
}
}
override fun onViewDetachedFromWindow(v: View?) {
view.removeOnAttachStateChangeListener(this)
}
})
}
CodePudding user response:
First inflate the layout in onCreateView() and you can do all your view related work in onViewCreated().
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentToolboxSheetBinding.inflate(layoutInflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
behavior = BottomSheetBehavior.from(view)
}
