Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 刀柄注射不适用于接收器_Android_Android Jetpack_Dagger Hilt - Fatal编程技术网

Android 刀柄注射不适用于接收器

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

使用Hilt的BroadcastReceiver内部的依赖项注入不起作用。我试图使用来自
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 class
onReceive
方法。这就是为什么你的物体没有被注入。 要测试,请在
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插件锡安,还是不走运。你能帮忙吗?