ANDROID 五月 02, 2019

Android • Bug Note

文章字数 3.8k 阅读约需 7 mins. 阅读次数 0

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'
}

错误输出如下:

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 {

    ...
}

0%