Issue
I get an occasional app crash report which shouldn't occur based on my understanding of the Android lifecycle. Obviously I'm wrong somehow.
I have an Activity which initializes an API interface in the onCreate and provides a method called getApi()
class MainActivity : AppCompatActivity(), IApiProvider...{
...
private lateinit var mApiInterface: ApiInterface
override fun onCreate(savedInstanceState: Bundle?) {
...
mApiInterface = ApiInterface.invoke(
ConnectivityInterceptor(applicationContext, this),
AuthorizationInterceptor(this),
prefs,
authenticator
)
...
}
override fun getApi(): ApiInterface {
return mApiInterface // THIS IS WHERE THE CRASH OCCURS
}
}
I also have a Fragment which attempts to grab this Api interface from the activity in the following fashion
class MyFragment()...{
private lateinit var mApiProvider: IApiProvider
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is IApiProvider) {
mApiProvider = context
} else {
throw RuntimeException("$context must implement IApiProvider")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
if (activity != null) {
mViewModel = ViewModelProvider(
this,
MyViewModelFactory(requireActivity().application, mApiProvider.getApi()) // This call causes the crash in the Activity
)
.get(LapTimingViewModel::class.java)
}
}
So even if the Activity gets recycled due to some Android memory management, shouldn't the Activity onCreate method be executed before the Fragment onCreate method and therefore the mApiInterface should be initialized?
Edit #1: Adding stacktrace
2022-03-24 12:45:32.600 23305-23305/hidden.package.name.debug E/AndroidRuntime: FATAL EXCEPTION: main
Process: hidden.package.name.debug, PID: 23305
java.lang.RuntimeException: Unable to start activity ComponentInfo{hidden.package.name.debug/hidden.package.name.MainActivity}: android.view.InflateException: Binary XML file line #11 in hidden.package.name.debug:layout/activity_main: Binary XML file line #47 in hidden.package.name.debug:layout/app_bar_main: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3527)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3702)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2151)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:250)
at android.app.ActivityThread.main(ActivityThread.java:7844)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)
Caused by: android.view.InflateException: Binary XML file line #11 in hidden.package.name.debug:layout/activity_main: Binary XML file line #47 in hidden.package.name.debug:layout/app_bar_main: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #47 in hidden.package.name.debug:layout/app_bar_main: Error inflating class fragment
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property mApiInterface has not been initialized
at hidden.package.name.MainActivity.getApi(MainActivity.kt:536)
at hidden.package.name.ui.laptiming.LapTimingFragment.onCreate(LapTimingFragment.kt:112)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2684)
at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:280)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1175)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
at androidx.fragment.app.FragmentManager.dispatchCreate(FragmentManager.java:2571)
at androidx.fragment.app.Fragment.restoreChildFragmentState(Fragment.java:1707)
at androidx.fragment.app.Fragment.onCreate(Fragment.java:1683)
at hidden.package.name.ui.home.BottomNavigationFragment.onCreate(BottomNavigationFragment.kt:62)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2684)
at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:280)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1175)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
at androidx.fragment.app.FragmentManager.dispatchCreate(FragmentManager.java:2571)
at androidx.fragment.app.Fragment.restoreChildFragmentState(Fragment.java:1707)
at androidx.fragment.app.Fragment.onCreate(Fragment.java:1683)
at androidx.navigation.fragment.NavHostFragment.onCreate(NavHostFragment.java:264)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2684)
at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:280)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1175)
2022-03-24 12:45:32.601 23305-23305/hidden.package.name.debug E/AndroidRuntime: at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:135)
at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:135)
at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:356)
at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:335)
at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1067)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:995)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1121)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1124)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.parseInclude(LayoutInflater.java:1261)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1117)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1082)
at android.view.LayoutInflater.inflate(LayoutInflater.java:680)
at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
at hidden.package.name.databinding.ActivityMainBinding.inflate(ActivityMainBinding.java:52)
at hidden.package.name.databinding.ActivityMainBinding.inflate(ActivityMainBinding.java:46)
at hidden.package.name.MainActivity.onCreate(MainActivity.kt:83)
at android.app.Activity.performCreate(Activity.java:8114)
at android.app.Activity.performCreate(Activity.java:8098)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3500)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3702)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2151)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:250)
at android.app.ActivityThread.main(ActivityThread.java:7844)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)
Solution
Found an answer thanks to @laalto
I changed my Activity onCreate from this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = ActivityMainBinding.inflate(layoutInflater)
val view = mBinding.root
setContentView(view)
val toolbar: Toolbar = findViewById(R.id.toolbar)
toolbar.visibility = View.GONE
setSupportActionBar(toolbar)
setupDrawerNav()
...
mApiInterface = ApiInterface.invoke(
ConnectivityInterceptor(applicationContext, this),
AuthorizationInterceptor(this),
prefs,
authenticator
)
...
}
to this
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
mApiInterface = ApiInterface.invoke(
ConnectivityInterceptor(applicationContext, this),
AuthorizationInterceptor(this),
prefs,
authenticator
)
mBinding = ActivityMainBinding.inflate(layoutInflater)
val view = mBinding.root
setContentView(view)
val toolbar: Toolbar = findViewById(R.id.toolbar)
toolbar.visibility = View.GONE
setSupportActionBar(toolbar)
setupDrawerNav()
Basically, I only bind the view after the init is done...
Answered By - woocassh
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.