You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Dagger注入DynamoDBMapper并适配AWSMobileClient初始化?

解决Dagger注入DynamoDBMapper时因AWSMobileClient未初始化导致的崩溃问题

这个问题的核心在于AWSMobileClient的初始化是异步操作,而Dagger会在应用启动阶段就尝试创建单例依赖(比如你的AmazonDynamoDBClient和DynamoDBMapper),这时候AWSMobileClient还没完成初始化,导致凭证提供者为空,最终引发崩溃。下面给你几个可行的解决方案:

方案一:等待AWSMobileClient初始化完成后再初始化Dagger组件

最直接的方式是确保Dagger组件在AWSMobileClient初始化完成后再创建。你可以在Application类中调整初始化顺序:

class MyApplication : Application() {
    lateinit var appComponent: AppComponent

    override fun onCreate() {
        super.onCreate()
        // 先初始化AWSMobileClient,回调中创建Dagger组件
        AWSMobileClient.getInstance().initialize(this) { userState ->
            Timber.d("AWSMobileClient initialized successfully, state: ${userState.userState}")
            // 初始化Dagger组件
            appComponent = DaggerAppComponent.create()
            // 这里可以通过LiveData或EventBus通知UI层Dagger已就绪
        }.execute()
    }
}

之后在Activity/Fragment中,需要确保appComponent已经初始化完成再使用(比如添加启动页显示加载状态,或者用LiveData监听初始化完成事件)。这种方式能彻底避免Dagger提前创建依赖的问题。

方案二:封装AWSMobileClient为可等待的单例

创建一个包装类,把AWSMobileClient的异步初始化转为可挂起的操作,确保依赖它的组件能等待初始化完成:

class AWSMobileClientManager private constructor() {
    lateinit var client: AWSMobileClient
    private val initDeferred = CompletableDeferred<Unit>()

    suspend fun initialize(context: Context) {
        if (!::client.isInitialized) {
            val callback = object : Callback<UserStateDetails> {
                override fun onResult(result: UserStateDetails?) {
                    client = AWSMobileClient.getInstance()
                    initDeferred.complete(Unit)
                }

                override fun onError(e: Exception?) {
                    initDeferred.completeExceptionally(e!!)
                }
            }
            AWSMobileClient.getInstance().initialize(context, callback).execute()
            initDeferred.await() // 等待初始化完成
        }
    }

    companion object {
        val instance by lazy { AWSMobileClientManager() }
    }
}

然后在Dagger模块中提供这个管理器,在Repository中注入它,并在使用DynamoDBMapper前先等待初始化:

// Dagger模块
@Module
class AwsModule {
    @Singleton
    @Provides
    fun provideAWSMobileClientManager(): AWSMobileClientManager {
        return AWSMobileClientManager.instance
    }
}

// Repository类
class MyRepository @Inject constructor(
    private val awsManager: AWSMobileClientManager
) {
    // 延迟初始化Mapper,确保调用时AWSMobileClient已就绪
    private val dynamoDbMapper: DynamoDBMapper by lazy {
        val credentials = awsManager.client.credentialsProvider
        val config = awsManager.client.configuration
        val ddbClient = AmazonDynamoDBClient(credentials).apply {
            setRegion(Region.getRegion(Regions.EU_WEST_2))
        }
        DynamoDBMapper.builder()
            .awsConfiguration(config)
            .dynamoDBClient(ddbClient)
            .build()
    }

    suspend fun getSomeData(itemId: String): MyDataItem? {
        // 先确保AWSMobileClient初始化完成
        awsManager.initialize(ApplicationProvider.getApplicationContext())
        // 再使用Mapper
        return dynamoDbMapper.load(MyDataItem::class.java, itemId)
    }
}

这种方式无需调整Dagger组件的初始化时机,而是把等待逻辑封装在Repository层,更灵活。

额外提示:考虑升级AWS SDK

你当前使用的AmazonDynamoDBClient是AWS SDK v1的类,官方已经推荐使用v2的DynamoDbClient(通过DynamoDbClient.builder()创建),v2的初始化方式更简洁,也更容易和协程等现代Android架构结合,建议后续考虑升级。

内容的提问来源于stack exchange,提问作者OliverDeLange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:36:52