【问题标题】:How to work with context singletons in Roboguice如何在 Roboguice 中使用上下文单例
【发布时间】:2012-09-20 14:22:36
【问题描述】:

我使用@ContextSingleton 来标记依赖于上下文注入的单例。然而,从 RoboGuice 源代码和我自己的测试来看,似乎它在 Application 上下文和不同的活动上下文之间产生了差异。这是完全有道理的,只是当我将它与这样的事件管理工具一起使用时——至少对我来说——有问题:

@ContextSingleton
public class Service {
    @Inject
    private Context context;

    public void doSomething(@Observes MyEvent ev) {
        ...
    }
}

虽然服务被定义为单例,但似乎在它第一次注入某个地方之前似乎没有创建它的实例,显然是通过延迟加载。因此,触发MyEvent 不会使听众调用。我们认为我们可以在我们的应用程序中“手动”预先加载类,例如

RoboGuice.get(context).getInstance(Service.class);

并因此注册监听器,但这只有在之后也注入EventManager 以触发事件而不是应用程序的Activity 中执行时才能正常工作。

因此,在理想的世界中,我希望我可以告诉 RoboGuice 应该将单例绑定到哪个上下文,就像这样

@ContextSingleton(MyApplication.class)
public class Service {
    ...
}

但显然这是不可能的。

我错过了什么?

【问题讨论】:

    标签: android dependency-injection guice roboguice


    【解决方案1】:

    我认为您错过了事件不会跨上下文传播并且是特定于上下文的 - 请参阅(旧但仍然有效)events documentation 中的“注意事项”部分。因此,即使您的单例在应用程序上下文中加载,它也无法知道每个活动的上下文中发生的事件。我认为他们这样做是有充分理由的,但也许如果您将Application 子类化,您可以注入一个EventManager 以供全球访问。

    我还没有尝试过,所以我不确定它是否会起作用,无论如何,你必须将事件注入到不同的 EventManager 中,所以你最好为此定义一个接口单例并以这种方式使用它,因为事件不会按照您希望的方式传播。

    【讨论】:

    • 那就有点可惜了。我知道跨活动的事件是一个坏主意,因为活动可能会或可能不会被实例化,并且可以随时被销毁。但是为什么我不能将单例具体限定在应用程序上下文中,保证一直呆在那里,这超出了我的理解。在我使用 RoboGuice 之前,我按照惯例对应用程序进行子类化并为我的所有“全局”对象提供 getter,我真的认为 RoboGuice 会为我解决/解开这个问题。无论如何,像这样只让事件管理器在全球范围内可访问可能总比没有好......
    • @tommyd 你总是可以写一个补丁 ;)
    • 是的,我想是的 :) 如果时间允许,如果我完全理解那里发生的事情,我会去看看。
    • 请注意,RG 3 将有一个 GlobalEventObserver 可以跨上下文传播事件
    【解决方案2】:

    @JRaymond 是对的。 RoboGuice 事件侦听器的实例不能在多个上下文中侦听事件。

    但这很容易解决。不要让你的单身人士直接听事件。每个活动都可以监听自己的事件,然后将单通置于给定状态:

    public class MyActivity extends RoboActivity {
        @Inject 
        private InsideAppManager mInsideAppManager;
    
        public void onHandleResumeEvent( @Observes OnResumeEvent onStartEvent ) {
            mInsideAppManager.setInsideApp(true);
        }
    
        public void onHandlePauseEvent( @Observes OnPauseEvent onStopEvent ) {
            mInsideAppManager.setInsideApp(false);
        }
    }
    

    还有你的单身:

    @Singleton
    public class InsideAppManager {
        private boolean isInsideApp;
    
        public boolean isInsideApp() {
            return isInsideApp;
        }
    
        public void setInsideApp(boolean isInsideApp) {
            this.isInsideApp = isInsideApp;
        }
    }
    

    【讨论】:

    • 是的,我们基本上在几个地方使用了这样的结构。只是我们将InsideAppManager 命名为简单的VolatileState,因为它以非持久方式跨不同上下文保存数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-24
    • 2012-01-07
    • 1970-01-01
    相关资源
    最近更新 更多