Android 刀柄注射不适用于接收器
使用Hilt的BroadcastReceiver内部的依赖项注入不起作用。我试图使用来自Android 刀柄注射不适用于接收器,android,android-jetpack,dagger-hilt,Android,Android Jetpack,Dagger Hilt,使用Hilt的BroadcastReceiver内部的依赖项注入不起作用。我试图使用来自main活动的警报调用BroadcastReceiver,我得到未初始化的PropertyAccessException。根据文档,它应该像向接收器添加@AndroidEntryPoint注释一样简单,但它不是 示例代码: @HiltAndroidApp class App: Application() { override fun onCreate() { super.onCreat
main活动的警报调用BroadcastReceiver
,我得到未初始化的PropertyAccessException
。根据文档,它应该像向接收器添加@AndroidEntryPoint
注释一样简单,但它不是
示例代码:
@HiltAndroidApp
class App: Application() {
override fun onCreate() {
super.onCreate()
Log.d(App::class.simpleName, "onCreate: Application")
}
}
class TestHiltInjection @Inject constructor() {
operator fun invoke() {
Log.d(TestHiltInjection::class.java.simpleName, "invoke called.")
}
}
@AndroidEntryPoint
class HiltBroadcastReceiver : BroadcastReceiver() {
@Inject lateinit var testHiltInjection: TestHiltInjection
override fun onReceive(context: Context?, intent: Intent?) {
testHiltInjection()
}
}
@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
)
}
}
App.kt:
@HiltAndroidApp
class App: Application() {
override fun onCreate() {
super.onCreate()
Log.d(App::class.simpleName, "onCreate: Application")
}
}
class TestHiltInjection @Inject constructor() {
operator fun invoke() {
Log.d(TestHiltInjection::class.java.simpleName, "invoke called.")
}
}
@AndroidEntryPoint
class HiltBroadcastReceiver : BroadcastReceiver() {
@Inject lateinit var testHiltInjection: TestHiltInjection
override fun onReceive(context: Context?, intent: Intent?) {
testHiltInjection()
}
}
@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
)
}
}
testhilt.kt:
@HiltAndroidApp
class App: Application() {
override fun onCreate() {
super.onCreate()
Log.d(App::class.simpleName, "onCreate: Application")
}
}
class TestHiltInjection @Inject constructor() {
operator fun invoke() {
Log.d(TestHiltInjection::class.java.simpleName, "invoke called.")
}
}
@AndroidEntryPoint
class HiltBroadcastReceiver : BroadcastReceiver() {
@Inject lateinit var testHiltInjection: TestHiltInjection
override fun onReceive(context: Context?, intent: Intent?) {
testHiltInjection()
}
}
@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
)
}
}
希尔顿接收机.kt:
@HiltAndroidApp
class App: Application() {
override fun onCreate() {
super.onCreate()
Log.d(App::class.simpleName, "onCreate: Application")
}
}
class TestHiltInjection @Inject constructor() {
operator fun invoke() {
Log.d(TestHiltInjection::class.java.simpleName, "invoke called.")
}
}
@AndroidEntryPoint
class HiltBroadcastReceiver : BroadcastReceiver() {
@Inject lateinit var testHiltInjection: TestHiltInjection
override fun onReceive(context: Context?, intent: Intent?) {
testHiltInjection()
}
}
@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
)
}
}
MainActivity.kt:
@HiltAndroidApp
class App: Application() {
override fun onCreate() {
super.onCreate()
Log.d(App::class.simpleName, "onCreate: Application")
}
}
class TestHiltInjection @Inject constructor() {
operator fun invoke() {
Log.d(TestHiltInjection::class.java.simpleName, "invoke called.")
}
}
@AndroidEntryPoint
class HiltBroadcastReceiver : BroadcastReceiver() {
@Inject lateinit var testHiltInjection: TestHiltInjection
override fun onReceive(context: Context?, intent: Intent?) {
testHiltInjection()
}
}
@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
我认为hilt目前不支持BroadcastReceiver。在说
注意:Hilt目前只支持扩展ComponentActivity的活动和扩展androidx库片段的片段,而不支持Android平台中的(现已弃用)片段
内部工作原理:Hilt为带注释的组件(活动、片段、BroadcastReceiver等)创建抽象类,BroadcastReceiver将生成的类扩展为字节码转换中的基类。在基类onReceive
中注入方法对象。但在生成的字节码类中,不会调用super classonReceive
方法。这就是为什么你的物体没有被注入。
要测试,请在testHiltInjection()之前在HiltBroadcastReceiver
类中添加以下代码。顺便说一下,它仍然处于Alpha模式
((HiltBroadcastReceiver_GeneratedInjector) BroadcastReceiverComponentManager.generatedComponent(context)).injectHiltBroadcastReceiver(UnsafeCasts.<HiltBroadcastReceiver>unsafeCast(this));
((HiltBroadcastReceiver\u GeneratedInjector)BroadcastReceiverComponentManager.generatedComponent(上下文)).injectHiltBroadcastReceiver(unsecast.unsecast(this));
更新:现在问题已在版本2.29.1-alpha
中修复。另外,不要忘记将hilt android gradle插件升级到2.29.1-alpha
或最新版本。更多信息
修复#1918:支持带有@AndroidEntryPoint转换的广播接收器。(ede018b)
更新:根据需要,问题应在匕首柄版本中修复。因此,只需使用版本2.29.1-alpha
或更高版本即可。别忘了更新hilt android gradle插件的版本
原始答案:有一个GitHub和一个。注入似乎不起作用,因为它实际上发生在生成的父类的onReceive()方法中。问题是你不能调用超级方法,因为它是抽象的。但您可以创建一个简单的包装器类来解决此问题:
抽象类BroadcastReceiver:BroadcastReceiver(){
@超级呼叫
重写接收(上下文:上下文,意图:意图){}
}
@雄蕊识别点
类MyBroadcastReceiver:HiltBroadcastReceiver(){
@注入lateinit变量testHiltInjection:testHiltInjection
覆盖接收(上下文:上下文?,意图:意图?){
super.onReceive(context,intent)/当前,由于刀柄错误,您不能将@AndroidEntryPoint
用于BroadcastReceiver。
相反,您使用这样的变通逻辑
@AndroidEntryPoint
public class SMSReceiver extends BroadcastReceiver {
@Inject
public DataManager dataManager;
@Override
public void onReceive(final Context context, Intent intent) {
}
}
如果要在BroadcastReceiver中插入SomeModule
创建新入口点
@EntryPoint
@InstallIn(ApplicationComponent::class)
interface MyEntryPoint {
fun getSomeModule: SomeModule
}
获取入口点并使用它
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val someModule : SomeModule =
EntryPoints.get(context?.applicationContext, MyEntryPoint::class.java)
.getSomeModule()
}
}
使用Hilt的稳定版本。您可以轻松地注入任何这样的变量
@AndroidEntryPoint
public class SMSReceiver extends BroadcastReceiver {
@Inject
public DataManager dataManager;
@Override
public void onReceive(final Context context, Intent intent) {
}
}
它工作得很好。是的,我知道它是在alpha模式下工作的,但我的想法是测试和报告错误。另外,在文档中,他们没有明确地表明BroadcastReceiver不受支持。解决方法不错。这看起来像是一个刀柄错误,文档确实说BroadcastReceiver受支持。我在他们的github@FrankHarper上对此提出了一个问题,这是一个很好的解决方法你的github问题:很好的发现!!我不敢相信谷歌在发布它之前没有发现它…一个相关的主题@ValeriyKatkov…你在匕首刀柄
标记向上投票同义词方面有足够的声誉。你能在这里做到吗:?似乎没有版主关心给刀柄
相关标记带来秩序,所以我试着合作我自己决定。@Valeriy Katkov我使用了提供的解决方法,非常感谢,但广播接收器仍然不会在我的应用程序中调用。还有什么需要做的吗?这就是我目前所做的。@Valeriy Katkov我也面临着同样的问题。我尝试了你建议的解决方法,并升级了hilt gradle插件锡安,还是不走运。你能帮忙吗?