需要重新创建屏幕时崩溃,依赖注入可能出现问题(类没有零参数构造函数)

问题描述 投票:0回答:1

我正在开发一个旧的 Android 项目。我对 Android 有一点了解,但我的重点是 iOS。所以也许我在这里错过了一些简单的东西。

问题: 主屏幕正在工作,但当需要重新创建时,应用程序崩溃。今天我在设置中触发它并更改位置权限。

错误

FATAL EXCEPTION: main
                                                                                                    Process: com.x.activities, PID: 16127
                                                                                                    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.x.activities/com.x.ui.home.HomeActivity}: android.view.InflateException: Binary XML file line #23 in com.xxx.activities:layout/activity_homescreen: Binary XML file line #23 in com.x.activities:layout/activity_homescreen: Error inflating class fragment
                                                                                                        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3782)
                                                                                                        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922)
                                                                                                        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
                                                                                                        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
                                                                                                        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
                                                                                                        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)
                                                                                                        at android.os.Handler.dispatchMessage(Handler.java:106)
                                                                                                        at android.os.Looper.loopOnce(Looper.java:205)
                                                                                                        at android.os.Looper.loop(Looper.java:294)
                                                                                                        at android.app.ActivityThread.main(ActivityThread.java:8177)
                                                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
                                                                                                    Caused by: android.view.InflateException: Binary XML file line #23 in com.x.activities:layout/activity_homescreen: Binary XML file line #23 in com.x.activities:layout/activity_homescreen: Error inflating class fragment
                                                                                                    Caused by: android.view.InflateException: Binary XML file line #23 in com.x.activities:layout/activity_homescreen: Error inflating class fragment
                                                                                                    Caused by: java.lang.RuntimeException: Cannot create an instance of class com.x.ui.home.HomeViewModel
                                                                                                        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:204)
                                                                                                        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:322)
                                                                                                        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:304)
                                                                                                        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:278)
                                                                                                        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.kt:128)
                                                                                                        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:187)
                                                                                                        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:153)
                                                                                                        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:53)
                                                                                                        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:35)
                                                                                                        at com.x.ui.homescreen.HomescreenFragment.getParentViewModel(HomescreenFragment.kt:47)
                                                                                                        at com.x.ui.homescreen.HomescreenFragment.observeParentViewModel(HomescreenFragment.kt:130)
                                                                                                        at com.x.ui.homescreen.HomescreenFragment.onViewCreated(HomescreenFragment.kt:96)
                                                                                                        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:1433)
                                                                                                        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2977)
                                                                                                        at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2888)
                                                                                                        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3129)
                                                                                                        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:1433)
                                                                                                        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2977)
2023-09-08 14:54:08.143 16127-16127 AndroidRuntime          com.x.activities              E     at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2888)
                                                                                                        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3129)
                                                                                                        at androidx.fragment.app.FragmentStateManager.ensureInflatedView(FragmentStateManager.java:394)
                                                                                                        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:260)
                                                                                                        at androidx.fragment.app.FragmentLayoutInflaterFactory.onCreateView(FragmentLayoutInflaterFactory.java:142)
                                                                                                        at androidx.fragment.app.FragmentController.onCreateView(FragmentController.java:136)
                                                                                                        at androidx.fragment.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:248)
                                                                                                        at androidx.fragment.app.FragmentActivity.onCreateView(FragmentActivity.java:227)
                                                                                                        at android.view.LayoutInflater.tryCreateView(LayoutInflater.java:1081)
                                                                                                        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1009)
                                                                                                        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:973)
                                                                                                        at android.view.LayoutInflater.rInflate(LayoutInflater.java:1135)
                                                                                                        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1096)
                                                                                                        at android.view.LayoutInflater.rInflate(LayoutInflater.java:1138)
                                                                                                        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1096)
                                                                                                        at android.view.LayoutInflater.inflate(LayoutInflater.java:694)
                                                                                                        at android.view.LayoutInflater.inflate(LayoutInflater.java:538)
                                                                                                        at android.view.LayoutInflater.inflate(LayoutInflater.java:485)
                                                                                                        at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:699)
                                                                                                        at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195)
                                                                                                        at com.x.ui.home.HomeActivity.onCreate(HomeActivity.kt:133)
                                                                                                        at android.app.Activity.performCreate(Activity.java:8595)
                                                                                                        at android.app.Activity.performCreate(Activity.java:8573)
                                                                                                        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456)
                                                                                                        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3764)
                                                                                                        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922)
                                                                                                        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
                                                                                                        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
                                                                                                        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
                                                                                                        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)
                                                                                                        at android.os.Handler.dispatchMessage(Handler.java:106)
                                                                                                        at android.os.Looper.loopOnce(Looper.java:205)
                                                                                                        at android.os.Looper.loop(Looper.java:294)
                                                                                                        at android.app.ActivityThread.main(ActivityThread.java:8177)
                                                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
                                                                                                    Caused by: java.lang.InstantiationException: java.lang.Class<com.x.ui.home.HomeViewModel> has no zero argument constructor
                                                                                                        at java.lang.Class.newInstance(Native Method)
                                                                                                        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:202)
                                                                                                        ... 61 more

主屏幕片段

class HomescreenFragment : BaseMvRxFragment() {

private val parentViewModel by homeViewModel() //line 47

  @Inject
  internal lateinit var viewModelFactory: HomescreenViewModel.Factory
  private val viewModel: HomescreenViewModel by fragmentViewModel()

  private val homescreenActionsController by lazy { HomescreenActionsController(requireActivity()) }

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
//...
        observeParentViewModel() //line 96
//...
  }

  private fun observeParentViewModel() =
        parentViewModel.permissionRequestResult.observeEvent(viewLifecycleOwner) { //line 130
            homescreenActionsController.onPermissionResult(it)
  }
//...
}

首页活动

class HomeActivity : AppCompatActivity(), HomeCallbacks, UsingLocation {

  @Inject
  lateinit var viewModelFactory: ViewModelProvider.Factory

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        NetComponent.instance.inject(this)
        initDagger()
        setContentView(R.layout.activity_homescreen) //line 133
///...
  }
///...
}

HomeViewModel

class HomeViewModel @Inject constructor(
    private val userInbox: UserInbox,
    private val prefUserInfo: PrefUserInfo,
    private val prefAppInfo: PrefAppInfo,
    private val prefOrgInfo: PrefOrgInfo,
    private val realmController: RealmController,
    private val api: Api,
    private val loginState: LoginState,
    private val application: LiveSafeApplication,
    private val initializers: AppInitializer
) : ViewModel(), PushJsonConsumer {

  init {
        NetComponent.instance.inject(this)
        ///...
  }

  companion object {
        fun Fragment.homeViewModel() = activityViewModels<HomeViewModel>()
  }
}

activity_homescreen.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/homescreen_wrapper"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/nav_host_fragment_container"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <fragment
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_main" /> //line 23
    </FrameLayout>

///...
</androidx.constraintlayout.widget.ConstraintLayout>

我发现的一个建议是替换:

private val parentViewModel by homeViewModel()

@Inject
lateinit var viewModelFactory2: ViewModelProvider.Factory

private val parentViewModel: HomeViewModel by viewModels { viewModelFactory2 }

如果我这样做,应用程序将不再崩溃,但函数observeParentViewModel中的代码不会被调用,所以我认为我得到了一个不同的实例。

parentViewModel
仅在
observeParentViewModel
函数中调用,因此如果我仍然可以调用homescreenActionsController.onPermissionResult

,我可以使用不同的策略

其他建议是创建一个自定义工厂,以便能够拥有一个不带参数的

HomeViewModel
,但我不明白如何传递参数才能创建一个
HomeViewModel

该项目未使用 Hilt,仅使用 Dagger。

java android kotlin androidx dagger
1个回答
0
投票

要修复 Android 项目中的“类没有零参数构造函数”错误,这里有一个简化的推荐解决方案:

  1. HomeViewModel
    创建一个可以处理依赖注入的自定义 ViewModel Factory。
class HomeViewModelFactory @Inject constructor(
    // Inject your dependencies here
) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(HomeViewModel::class.java)) {
            @Suppress("UNCHECKED_CAST")
            return HomeViewModel(
                // Pass the injected dependencies here
            ) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}
  1. 确保您设置了 Dagger 模块来提供
    HomeViewModel
    HomeViewModelFactory
    所需的依赖项。
@Module
class AppModule {
    // Provide your dependencies here
}
  1. 更新您的
    HomescreenFragment
    以将 ViewModel 与自定义工厂一起使用,以实现正确的依赖项注入。
class HomescreenFragment : BaseMvRxFragment() {

    @Inject
    lateinit var viewModelFactory: HomeViewModelFactory

    private val parentViewModel: HomeViewModel by viewModels { viewModelFactory }

    // ...
}

通过执行这些步骤,您的应用程序应该不再崩溃,并且您将能够使用

parentViewModel
及其正确注入的依赖项。确保您的 Dagger 设置提供所需的依赖项。

© www.soinside.com 2019 - 2024. All rights reserved.