18

使用 Hilt内部的依赖注入BroadcastReceiver不起作用。我尝试BroadcastReceiver使用警报调用 aMainActivity并且我得到了UninitializedPropertyAccessException。根据文档,它应该像将@AndroidEntryPoint注释添加到接收器一样简单,但事实并非如此。

示例代码:

应用程序.kt:

@HiltAndroidApp
class App: Application() {
    override fun onCreate() {
        super.onCreate()
        Log.d(App::class.simpleName, "onCreate: Application")
    }
}

TestHiltInjection.kt:

class TestHiltInjection @Inject constructor() {

    operator fun invoke() {
        Log.d(TestHiltInjection::class.java.simpleName, "invoke called.")
    }
}

HiltBroadcastReceiver.kt:

@AndroidEntryPoint
class HiltBroadcastReceiver : BroadcastReceiver() {

    @Inject lateinit var testHiltInjection: TestHiltInjection

    override fun onReceive(context: Context?, intent: Intent?) {
        testHiltInjection()
    }
}

MainActivity.kt:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val manager = getSystemService(Context.ALARM_SERVICE) as AlarmManager

        val pending = PendingIntent
            .getBroadcast(this, 0, Intent(this, HiltBroadcastReceiver::class.java), 0)
        manager.setInexactRepeating(
            AlarmManager.ELAPSED_REALTIME_WAKEUP,
            15000, 15000,
            pending
        )
    }
}

输出日志猫:

kotlin.UninitializedPropertyAccessException: lateinit property testHiltInjection has not been initialized

更新

问题已在 2.29.1 版本上解决,只需使用@AndroidEntryPoint

4

5 回答 5

30

更新:根据问题应该在Dagger Hilt的2.29.1版本中修复。因此,只需使用版本2.29.1-alpha或更高版本。不要忘记更新hilt-android-gradle-plugin版本


原始答案:有一个 GitHub问题解决方法。似乎注入不起作用,因为它实际上发生在onReceive()生成的父类的方法内部。问题是你不能调用 super 方法,因为它是抽象的。但是你可以创建一个简单的包装类来解决这个问题:

abstract class HiltBroadcastReceiver : BroadcastReceiver() {
  @CallSuper
  override fun onReceive(context: Context, intent: Intent) {}
}

@AndroidEntryPoint
class MyBroadcastReceiver : HiltBroadcastReceiver() {
  @Inject lateinit var testHiltInjection: TestHiltInjection

  override fun onReceive(context: Context?, intent: Intent?) {
    super.onReceive(context, intent) // <-- it's the trick

    ...
  }
}
于 2020-06-17T16:37:12.477 回答
6

我认为 hilt 目前不支持 BroadcastReceiver。在https://dagger.dev/hilt/android-entry-point中说

注意:Hilt 目前只支持扩展 ComponentActivity 的 Activity 和扩展 androidx 库 Fragment 的 Fragment,不支持 Android 平台中的(现已弃用的)Fragment。

它如何在内部工作:Hilt 为带@AndroidEntryPoint注释的组件(Activity、Fragment、BroadcastReceiver 等)创建抽象类,并且您的 BroadcastReceiver 将生成的类扩展为字节码转换中的基类。在基类onReceive方法中注入对象。但是在生成的字节码类超类onReceive方法中没有被调用。这就是为什么你的对象没有被注入。testHiltInjection()要在HiltBroadcastReceiver课堂前测试添加以下代码。顺便说一句,它仍处于 Alpha 模式。

((HiltBroadcastReceiver_GeneratedInjector) BroadcastReceiverComponentManager.generatedComponent(context)).injectHiltBroadcastReceiver(UnsafeCasts.<HiltBroadcastReceiver>unsafeCast(this));

更新:现在问题已在版本中修复2.29.1-alpha。也不要忘记将hilt-android-gradle-plugin版本升级到2.29.1-alpha或最新。有关发布的更多信息。

修复 #1918:使用 @AndroidEntryPoint 转换支持 BroadcastReceiver。(ede018b)

于 2020-06-12T11:39:33.903 回答
2

使用稳定版本的 Hilt。你可以很容易地注入任何这样的变量

@AndroidEntryPoint
public class SMSReceiver extends BroadcastReceiver {
    @Inject
    public DataManager dataManager;

    @Override
    public void onReceive(final Context context, Intent intent) {
    }
}
于 2021-05-27T06:53:48.523 回答
-1

Hilt 现在很稳定。它现在很简单:

@AndroidEntryPoint
class MyAppWidget : AppWidgetProvider() {

@Inject
lateinit var getMyUseCase: MyUseCase
于 2021-09-08T19:26:25.963 回答
-1

@AndroidEntryPoint目前,由于 Hilt 错误,您不能用于 BroadcastReceiver。相反,您使用这样的解决方法逻辑

如果你想在 BroadcastReceiver 中注入 SomeModule

  1. 创建新的入口点

    @EntryPoint
    @InstallIn(ApplicationComponent::class)
    interface MyEntryPoint {
        fun getSomeModule: SomeModule
    }
    
  2. 获取入口点并使用它

    class MyBroadcastReceiver : BroadcastReceiver() {
       override fun onReceive(context: Context?, intent: Intent?) {
        val someModule : SomeModule =
          EntryPoints.get(context?.applicationContext, MyEntryPoint::class.java)
       .getSomeModule()
      }
    }
    
于 2020-09-17T06:23:58.753 回答