我遇到了使用Dagger2保存“缓存”数据的问题。 我有Application Component和Authentication Subcomponent 。 Authentication Subcomponent具有缓存模块: 前两个缓存对象工作正常。 国家列表有问题。 每 ...
提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供 中文繁体 英文版本 中英对照 版本,有任何建议请联系yoyou2525@163.com。
我将 Dagger 添加到我的旧 Android 应用程序中,并试图弄清楚如何处理依赖于非 Dagger 对象的依赖项,这些对象在正常应用程序初始化期间创建但在后台 + 不活动后的活动重启期间未重新创建。
在旧代码中,在身份验证代码路径期间,我们构造了一个“会话”object,其中包含创建经过身份验证的 Retrofit 对象所需的令牌和其他内容。 某些活动依赖于存在的 session object,并且用户在不通过身份验证代码路径的情况下无法正常访问它们。 但是,如果应用程序处于非活动状态然后稍后恢复,则平台将尝试直接重新创建活动而不通过身份验证代码路径,因此 session object 将为 Z37A6259CC0C1DAE29BD9A7866489DFF。
为了防止这种情况发生,历史上依赖于登录的每个活动都派生自“SessionActivity”,它的 onCreate 检查我们是否已登录,如果没有完成活动并启动应用程序的入口点。 (这将触发“会话” object 被重新创建;用户将不得不再次导航回该屏幕,但至少没有崩溃)
class SessionActivity {
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if( LegacySingleton.getInstance().session == null ) {
{
Intent intent = new Intent(this, LauncherActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
return;
}
}
}
我现在正在添加 Dagger,并且希望能够注入一个 Retrofit object,它是使用 Z21D6F40CFB511982E4424E0E250A95549EB269693131 构建的 Retrofit object
@Provides
fun provideRetrofit(): Retrofit {
return LegacySingleton.getInstance().session!!.authenticatedRetrofit
}
然后依赖于登录的示例活动将具有类似的 onCreate
@Override
protected void onCreate(Bundle savedInstanceState)
{
((MyComponentProvider) getApplicationContext()).getComponent().inject(this);
super.onCreate(savedInstanceState);
}
有一个明显的问题:如果 LegacySingleton.getInstance().session 返回 null (因为它会在重新创建路径中)然后我们会崩溃。 是否有一个共同的模式来解决这个问题?
如果 session 是 null,我的第一个倾向是在 provideRetrofit 中抛出 IllegalStateException,然后依赖登录的活动会说
@Override
protected void onCreate(Bundle savedInstanceState)
{
try {
((MyComponentProvider) getApplicationContext()).getComponent().inject(this);
} catch (ex: IllegalStateException) {
Intent intent = new Intent(this, LauncherActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
return;
}
super.onCreate(savedInstanceState);
}
(显然这将被考虑到辅助方法中,但为了简单起见在这里写出来)
但是,这不起作用,因为 Android 要求所有对 onCreate 的调用都调用到 super.onCreate。
我可以说
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
try {
((MyComponentProvider) getApplicationContext()).getComponent().inject(this);
} catch (ex: IllegalStateException) {
Intent intent = new Intent(this, LauncherActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
return;
}
}
但这打破了在super.onCreate之前注入的匕首原则。 (然后确保在 super.onCreate 回调到派生的 class 并需要其中一个依赖项的情况下准备好依赖项)所以这在某些情况下可能有效,但如果有人开始依赖 super.onCreate 中的这些依赖项,那么我会在运行时命中 NPE。 不是很好。
我可以执行注入并跟踪它是否成功,例如
@Override
protected void onCreate(Bundle savedInstanceState)
{
Val injectionSucceeded = try {
((MyComponentProvider) getApplicationContext()).getComponent().inject(this);
true
} catch (ex: IllegalStateException) {
false
}
super.onCreate(savedInstanceState);
If (!injectionSucceeded)
Intent intent = new Intent(this, LauncherActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
return;
}
}
但是和尝试2有同样的问题; 如果注入失败,那么无论如何我都会调用 super.onCreate 并且并非所有依赖项都可能已被注入。
我本可以提供 Nullable 对象
@Provides
fun provideRetrofit(): Retrofit? {
return LegacySingleton.getInstance().session?.authenticatedRetrofit
}
但是每个客户在使用它们之前都需要检查依赖项的可空性,这将是一个巨大的痛苦。 (我什至不确定这是否可能)
Google 的 Dagger 代码实验室暗示了这个问题: https://developer.android.com/codelabs/android-dagger#12
重要提示:进行条件字段注入(就像我们在 MainActivity.kt 中所做的那样,仅当用户登录时才进行注入)是非常危险的。 开发人员必须了解这些条件,并且在与注入的字段交互时可能会遇到 NullPointerExceptions。 为了避免这个问题,我们可以通过创建一个 SplashScreen 来添加一些间接性,该 SplashScreen 根据用户的 state 路由到 Registration、Login 或 Main。
但这对于一个现有的应用程序来说似乎并不实用,它有十几个 SessionActivity 子类,这些子类想要用 Retrofit 对象注入自己。
有没有人有更好的主意?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.