问题
I have a problem, I added three textView (textView, textView2, textView3) and imageView to fragment_home.xml and when I try to run the application on the emulator in Android Studio I get the error lateinit property homeViewModel has not been initialized.
homeFragment.kt
class homeFragment : Fragment() {
private lateinit var homeViewModel: homeViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel =
ViewModelProviders.of(this).get(homeViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = root.findViewById(R.id.text_home)
homeViewModel.text.observe(this, Observer {
textView.text = it
})
return root
}
}
error log
6728-6728/com.radex.mysummercarmanual E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.radex.mysummercarmanual, PID: 6728
kotlin.UninitializedPropertyAccessException: lateinit property homeViewModel has not been initialized
at com.radex.mysummercarmanual.ui.home.homeFragment.onCreateView(homeFragment.kt:23)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2439)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
at androidx.fragment.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2646)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2416)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2372)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3273)
at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
at androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2466)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1483)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3269)
at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:620)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1391)
at android.app.Activity.performStart(Activity.java:7157)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:2937)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
回答1:
- Try initialise your viewModel inside
onActivityCreated() - Don't observe or initiate you ViewModel inside
onCreateView() - Rename your class name from
homeFragmenttoHomeFragmentandhomeViewModeltoHomeViewModel - You don't need to do findViewMyId in Kotlin. you can access view directly ID.
The change Idea is bellow
class HomeFragment : Fragment() { private lateinit var homeViewModel: HomeViewModel override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val root = inflater.inflate(R.layout.fragment_home, container, false) return root } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) homeViewModel = ViewModelProviders.of(this).get(HomeViewModel::class.java) homeViewModel.text.observe(this, Observer { text_home.text = it }) } }
回答2:
When you initialize homeViewModel, you reference an uninitialized one so it gives you the error.
ViewModelProviders.of(this).get(***homeViewModel***::class.java)
I think the class name of your ViewModel should be HomeViewModel, so try this one:
private lateinit var homeViewModel: HomeViewModel
...
homeViewModel = ViewModelProviders.of(this).get(HomeViewModel::class.java)
回答3:
According to your code, as you're inside fragment do not initialize ViewModel inside onCreateView(), simply means let the view create first then initilalize viewModel.
To initialize viewModel you have to override onActivityCreated() method and initialize viewModel inside it. Your code will be like this:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
homeViewModel = ViewModelProviders.of(activity!!)[HomeViewModel::class.java]
homeViewModel.text.observe(this, Observer {
text_home.text = it
})
}
And notice here i pass activity!! rather than this, cause you just can't get the activity context or getActivity() directly whenever you're inside the fragment just by calling this. You have to tell manually. So your viewModel instantiation will be like this:
homeViewModel = ViewModelProviders.of(activity!!)[HomeViewModel::class.java]
Or You could use if block, like this:
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if(!::homeViewModel.isInitialized){
homeViewModel = ViewModelProviders.of(activity!!)[HomeViewModel::class.java]
homeViewModel.text.observe(this, Observer {
text_home.text = it
})
}
}
来源:https://stackoverflow.com/questions/58964019/lateinit-property-homeviewmodel-has-not-been-initialized