I am working on an application. I am trying to restore the state, when I return to the application from putting it into the background. I got an exception for which I currently have no idea why it happened. So, I decided to post here, to hopefully have someone spot what I am unable to see currently.
Exception:
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.mgr/com.mgr.MainActivity}:
java.lang.RuntimeException: An exception happened in constructor of class com.mgr.ui.viewmodels.MainViewModel
This can be traced back to: androidx.lifecycle.ViewModelProvider.Factory
internal fun <T : ViewModel?> newInstance(
modelClass: Class<T>,
constructor: Constructor<T>,
vararg params: Any
): T {
return try {
constructor.newInstance(*params)
} catch (e: IllegalAccessException) {
throw RuntimeException("Failed to access $modelClass", e)
} catch (e: InstantiationException) {
throw RuntimeException("A $modelClass cannot be instantiated.", e)
} catch (e: InvocationTargetException) {
throw RuntimeException(
"An exception happened in constructor of $modelClass", e.cause
)
}
}
More of my own code now:
MainViewModel.tk
@HiltViewModel
class MainViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
) : ViewModel()
{
companion object {
const val UI_MENU_STATE = "ui.menu.state"
}
init {
savedStateHandle.get<Boolean>(UI_MENU_STATE)?.let {
m -> onMenuStateChange(m);
}
}
private var m_title by mutableStateOf("")
private var displayMenu by mutableStateOf( false)
var tosVisible by mutableStateOf( false)
internal set
fun updateTitleState(title: String){
m_title = title;
}
fun onMenuStateChange(open: Boolean){
Log.d("App", open.toString());
displayMenu = open;
savedStateHandle.set<Boolean>(UI_MENU_STATE, displayMenu);
}
fun isMenuOpen(): Boolean {
return displayMenu;
}
fun getTitle(): String { return m_title; }
}
MainActivity:
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val mainViewModel = ViewModelProvider(
this,
SavedStateViewModelFactory(application, this)
)[MainViewModel::class.java]
setContent {
MgrTheme {
Surface(color = MaterialTheme.colorScheme.background) { Main(mainViewModel) }
}
}
}
}
FULL STACK TRACE:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mgr, PID: 11242
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mgr/com.mgr.MainActivity}: java.lang.RuntimeException: An exception happened in constructor of class com.mgr.ui.viewmodels.MainViewModel
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3676)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3813)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
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:2308)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7898)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Caused by: java.lang.RuntimeException: An exception happened in constructor of class com.mgr.ui.viewmodels.MainViewModel
at androidx.lifecycle.SavedStateViewModelFactoryKt.newInstance(SavedStateViewModelFactory.kt:234)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:133)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153)
at com.mgr.MainActivity.onCreate(MainActivity.kt:43)
at android.app.Activity.performCreate(Activity.java:8290)
at android.app.Activity.performCreate(Activity.java:8269)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1384)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3657)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3813)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
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:2308)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7898)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'void androidx.compose.runtime.MutableState.setValue(java.lang.Object)' on a null object reference
at com.mgr.ui.viewmodels.MainViewModel.setDisplayMenu(MainViewModel.kt:54)
at com.mgr.ui.viewmodels.MainViewModel.onMenuStateChange(MainViewModel.kt:40)
at com.mgr.ui.viewmodels.MainViewModel.<init>(MainViewModel.kt:24)
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.SavedStateViewModelFactoryKt.newInstance(SavedStateViewModelFactory.kt:228)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:133)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153)
at com.mgr.MainActivity.onCreate(MainActivity.kt:43)
at android.app.Activity.performCreate(Activity.java:8290)
at android.app.Activity.performCreate(Activity.java:8269)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1384)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3657)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3813)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
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:2308)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7898)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
EDIT: Passing into a separate @Composable
method.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Main(viewModel: MainViewModel = androidx.lifecycle.viewmodel.compose.viewModel()) {
CodePudding user response:
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'void androidx.compose.runtime.MutableState.setValue(java.lang.Object)' on a null object reference
You can try moving your init {}
block to be after you declare displayMenu
. I am not confident that this will work, but it is worth a try.
If that does not help, then you may need to postpone your use of the SavedStateHandle
until sometime when the MutableState
is ready for use.