ViewBinding
在 Activity / Fragment 中通过声明 layout id 获取 View
在 Gradle 6.5 后, 若想直接使用 layout id,在 app 文件夹下 的build.gradle 添加如下代码启用该功能。
PS: Google 已不建议在 Activity / Fragment 中直接使用layout id,建议迁移至 ViewBinding 或 DataBinding。
plugins {
...
// add this
id 'kotlin-android'
id 'kotlin-android-extensions'
}
Navigation
navHostFragment: NavController Error
错误输出如下:
java.lang.RuntimeException: Unable to start activity ComponentInfo{xxx.MainActivity}: java.lang.IllegalStateException: Activity xxx.MainActivity@xxx does not have a NavController set on xxx
解决方案:在需要使用到 NavController 的地方进行如下设置(如:MainActivity):
- before
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// set up the default AppBar to auto change the correct label
setupActionBarWithNavController(findNavController(R.id.navHostFragment))
}
}
- after
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.navHostFragment) as NavHostFragment
navController = navHostFragment.navController
// 设置 ActionBar
setupActionBarWithNavController(navController)
}
}
如果你不想使用代码控制 Navigation,也可直接在 xml 文件中对布局进行直接修改:
将 FragmentContainerView
修改为 fragment
即可
- 修改前
<androidx.fragment.app.FragmentContainerView
android:id="@+id/navHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav"/>
- 修改后
<fragment
android:id="@+id/navHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav"/>
Cannot resolve symbol ‘com.xxx.xxxFragmentArgs’ in XML
若配合使用 DataBinding 与 Navigation 并在 Activity / Fragment 间进行传值:
<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">
<data>
<variable
name="args"
type="com.xxx.xxxFragmentArgs"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".xxxFragment">
...
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
则需在 build.gradle 文件中添加如下代码:
sourceSets {
main {
kotlin {
srcDirs += 'build/generated/source/navigation-args'
}
}
}
若需使用 Java:
sourceSets {
main {
java {
srcDirs += 'build/generated/source/navigation-args'
}
}
}
Room
Cannot create an instance of xxx.xxxViewModel
如果你想使用懒加载的方式创建 ViewModel:
private val mViewModel: MyViewModel by viewModels()
则需要在 app 文件夹下的 build.gradle 文件中添加如下代码:
plugins {
...
// 添加
id 'kotlin-kapt'
}
...
dependencies {
implementation 'androidx.core:core-ktx:x.x.x'
implementation 'androidx.appcompat:appcompat:x.x.x'
...
// 添加
kapt "androidx.room:room-compiler:2.4.2"
}
如果使用 Hilt 对 ViewModel 进行注入:
@HiltViewModel
class RecipesViewModel @Inject constructor(
application: Application,
private val dataStoreRepository: DataStoreRepository
) : AndroidViewModel(application) {
...
}
Dagger Hilt
Unresolved reference: ApplicationComponent
当 Hilt 更新版本大于:2.31
后, ApplicationComponent
注解将被 Google 移除。
新版的 ApplicationComponent 注解被替换为了 SingletonComponent
- 版本更新前
@InstallIn(ApplicationComponent::class)
@Module
object NetworkModule {
...
}
- 版本更新后
@InstallIn(SingletonComponent::class)
@Module
object NetworkModule {
...
}