如何在AppWidgetProvider中正确实例化Presenter?
AppWidgetProvider中设置Presenter未初始化问题解决方案
问题根源
AppWidgetProvider本质是
BroadcastReceiver的子类,系统每次触发桌面部件相关的广播时,都会创建一个全新的AppWidgetProvider实例处理回调,处理完成后该实例就会被回收。你在onEnabled回调的实例中初始化的presenter成员变量,和后续onUpdate回调拿到的实例完全不是同一个对象,因此会出现未初始化的报错,和两个方法的调用先后顺序无关。
正确实现方案
方案1:使用全局单例Presenter(简单场景适用)
将Presenter设置为全局唯一实例,初始化时使用
ApplicationContext避免内存泄漏,不要持有AppWidgetProvider实例:class MyWidgetProvider : AppWidgetProvider() { // 放在伴生对象中,全局唯一 private companion object { private var presenter: Presenter? = null } override fun onEnabled(context: Context?) { super.onEnabled(context) Log.d("DEBUG", "Inside onEnabled") // 仅首次添加部件时初始化,使用Application context,不要传入当前AppWidgetProvider实例 if (presenter == null) { presenter = Presenter(context!!.applicationContext) } } override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { super.onUpdate(context, appWidgetManager, appWidgetIds) Log.d("DEBUG", "Inside onUpdate") presenter?.onUpdate(context, appWidgetIds) } override fun onDisabled(context: Context?) { super.onDisabled(context) // 最后一个部件被删除时清空资源,避免内存泄漏 presenter = null } }方案2:使用依赖注入框架(中大型项目适用)
如果你使用Hilt、Koin等依赖注入框架,直接给AppWidgetProvider添加注入注解,由框架注入Presenter实例即可,无需手动管理生命周期。
以Hilt为例示例:@AndroidEntryPoint class MyWidgetProvider : AppWidgetProvider() { @Inject lateinit var presenter: Presenter override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { super.onUpdate(context, appWidgetManager, appWidgetIds) presenter.onUpdate(context, appWidgetIds) } }提前在依赖注入框架中配置好Presenter的提供规则后,框架会在每次创建AppWidgetProvider实例时自动完成注入。
方案3:抽离业务逻辑到独立管理类
完全解耦业务逻辑和AppWidgetProvider的实例,创建一个独立的单例管理类处理桌面部件的所有业务,每次回调到AppWidgetProvider的生命周期方法时,直接调用管理类的对应方法即可,无需在AppWidgetProvider中持有Presenter实例。
内容的提问来源于stack exchange,提问作者suhas_sm
相关产品推荐
相关产品推荐

