使用匕首时如何初始化ViewModel



我开始学习dagger了。我试图从ViewModel中获取字符串,出现错误:

FATAL EXCEPTION: main
Process: com.sem.daggersimple, PID: 7882
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sem.daggersimple/com.sem.daggersimple.presentation.MainActivity}: android.view.InflateException: Binary XML file line #26 in com.sem.daggersimple:layout/activity_main: Binary XML file line #26 in com.sem.daggersimple:layout/activity_main: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3450)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3602)
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:2067)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7697)

...

Caused by: android.view.InflateException: Binary XML file line #26 in com.sem.daggersimple:layout/activity_main: Binary XML file line #26 in com.sem.daggersimple:layout/activity_main: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #26 in com.sem.daggersimple:layout/activity_main: Error inflating class fragment
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property stringViewModel has not been initialized
at com.sem.daggersimple.presentation.StringFragment.getStringViewModel(StringFragment.kt:24)
at com.sem.daggersimple.presentation.StringFragment.onCreateView(StringFragment.kt:43)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963)

...

at com.sem.daggersimple.presentation.MainActivity.onCreate(MainActivity.kt:20)

MainActivity:

class MainActivity : AppCompatActivity() {

@Inject
lateinit var stringViewModel: StringViewModel

private var binding: ActivityMainBinding? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

appComponent.inject(this)

}
}

StringFragment:

class StringFragment : Fragment() {
private var binding : FragmentStringBinding? = null
@Inject
lateinit var stringViewModel: StringViewModel
override fun onAttach(context: Context) {
super.onAttach(context)
// Grabs the registrationComponent from the Activity and injects this Fragment
// (activity as MainActivity).
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_string, container, false)
// stringViewModel.getString.
Log.d("stringViewModel","stringViewModel = " + stringViewModel.getString.get(0))
binding?.textView?.text = stringViewModel.getString
return binding?.root
}
}

StringRepository:

class StringRepository @Inject constructor() {
override fun toString() : String = "какой-то текст"
}

StringUseCase:

class StringUseCase @Inject constructor(private val repository: StringRepository) {
fun getString() : String {
return repository.toString()
}
}

StringViewModel:

class StringViewModel @Inject constructor(private val stringUseCase: StringUseCase) : ViewModel() {
val getString = stringUseCase.getString()
}

App:

class App : Application() {
lateinit var appComponent: AppComponent
override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent.create()
}
}
val Context.appComponent: AppComponent
get() = when(this) {
is App -> appComponent
else -> this.applicationContext.appComponent
}

AppComponent:

@Component(modules = [AppModule::class])
interface AppComponent {
fun inject(mainActivity: MainActivity)
fun inject(stringFragment: StringFragment)
}

AppModule:

@Module
object AppModule {

@Provides
fun provideStringViewModel(stringUseCase: StringUseCase) : StringViewModel {
return StringViewModel(stringUseCase)
}
@Provides
fun provideStringUseCase(repository: StringRepository) : StringUseCase {
return StringUseCase(repository)
}
@Provides
fun provideStringRepository() : StringRepository {
return StringRepository()
}
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context=".presentation.MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/framelayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/rd_fragment"
android:name="com.sem.daggersimple.presentation.StringFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

fragment_string.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".presentation.StringFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</layout>

附言:我不使用Hilt

不能将var用于延迟初始化委派属性。您应该使用val。您可以使用其中任何一个来初始化视图模型。

val stringViewModel by viewModels<StringViewModel>() 
val stringViewModel :StringViewModel by viewModels()

相关内容

  • 没有找到相关文章

最新更新