繁体   English   中英

重新创建活动后,如何处理onCreate中Dagger注入所需的未初始化资源?

How to handle uninitialized resources required for Dagger injection in onCreate after activity re-creation?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在将Dagger添加到我的旧版Android应用程序中,并试图弄清楚如何处理依赖非Dagger对象的依赖关系,这些依赖关系是在正常应用初始化期间创建的,但是在后台+不活动之后的活动重新启动期间不会重新创建。

现有代码

在旧代码中,在身份验证代码路径中,我们构造了一个“会话”对象,其中包含令牌和创建经过身份验证的Retrofit对象所需的其他内容。 某些活动依赖于存在的会话对象,并且用户没有通过身份验证代码路径的常规方式无法到达它们。 但是,如果应用程序变为非活动状态,然后在以后恢复,则平台将尝试直接重新创建活动,而不经过身份验证代码路径,因此会话对象将为null。

为了避免这种情况,从历史上看,每个依赖于登录的活动都源自“ SessionActivity”,其onCreate检查我们是否已登录,是否完成活动并启动应用程序的入口点。 (这将触发“会话”对象的重新创建;用户将不得不再次导航回到该屏幕,但至少没有崩溃)

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对象。

@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(将在重新创建路径中返回),那么我们将崩溃。 是否有解决此问题的通用模式?

尝试1:

我的第一个倾向是,如果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进行。

尝试2:

我可以说

@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回调到派生类的情况下已经准备好依赖项,并且需要这些依赖项之一)因此,这在某些情况下可能会起作用,但是如果有人开始依赖super.onCreate中的那些依赖项,那么我将在运行时命中NPE。 不是很好。

尝试3:

我可以执行注入并跟踪其是否成功,例如

@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,并且并非所有依赖项都已注入。

尝试4:

我本来可以提供Nullable对象

@Provides
fun provideRetrofit(): Retrofit? {
    return LegacySingleton.getInstance().session?.authenticatedRetrofit
}

但是每个客户都需要在使用依赖项之前检查其为空性,这将是一个巨大的痛苦。 (我什至不确定这是否可行)

Codelab建议:

Google的Dagger代码实验室暗示了此问题: https : //developer.android.com/codelabs/android-dagger#12

重要提示:进行条件字段注入(就像仅在用户登录时进行注入时一样,在MainActivity.kt中进行)是非常危险的。 开发人员必须了解条件,并且与注入的字段进行交互时,您可能会遇到NullPointerExceptions的风险。 为避免此问题,我们可以通过创建一个SplashScreen来添加一些间接性,该SplashScreen可以根据用户的状态路由到Registration,Login或Main。

但这对于具有数十个SessionActivity子类想要向其注入Retrofit对象的现有应用程序似乎并不实际。

有谁有更好的主意吗?

问题暂未有回复.您可以查看右边的相关问题.
1 匕首2清单重新创建

我遇到了使用Dagger2保存“缓存”数据的问题。 我有Application Component和Authentication Subcomponent 。 Authentication Subcomponent具有缓存模块: 前两个缓存对象工作正常。 国家列表有问题。 每 ...

2 Koin FragmentFactory 无法处理活动重新创建

我正在使用最新的 Koin 版本3.1.2 。 我有一个基本的Fragment ,它接受一个 String 参数给它的构造函数。 我的 Koin 设置如下: 活动: 分段: Koin模块: 为了模拟活动重新创建,我在开发人员选项中打开了Don't keep activities标志 ...

3 Android:方向更改后如何禁止重新创建Activity?

我有一个带有Frgment的Android活动。 当我的应用程序启动时,一个列表视图将加载从服务器发送的10个元素。 (简单的请求)。 当我更改设备的方向时,将重新创建该活动,同时还会看到微调框,其中包含我的请求以加载列表视图。 我该如何禁止重新创建活动? 我已经设置了标志 ...

4 活动重新创建意图附加项为空

我的应用程序包含MainActivity并使用全屏片段来显示内容。 我正在尝试在应用程序重新创建期间实现以下功能(当应用程序已经在后台运行了很长时间,被系统杀死然后它被带到了前台) 如果用户手动重新创建应用程序(通过从最近的应用程序列表中选择应用程序),则应重新创建主活动,然后重新创 ...

6 如何添加 Fragment 以便它不会在 Activity 重新创建中保留?

我正在动态地向/从我的活动添加和删除视图。 这些视图中的每一个都分配了一个 id 并充当特定片段的容器。 我使用条件逻辑向这些视图中的每一个添加一个片段,如下所示: 这种条件逻辑确保给定的 View 在 Activity 的生命周期内只添加了一次 Fragment。 除非重新创建活动(例如由于 ...

8 关于配置更改和上下文的活动重新创建的说明

我对Android开发很陌生,我正在寻找有关我正面临的问题的解释,以便更深入地了解Android。 我有这段代码: 如果下拉列表可见并且配置发生更改(屏幕方向),我将收到BadTokenException。 我知道活动被销毁并且创建了一个新的替换它,但是我不太明白实际发生了什 ...

2012-01-27 17:18:57 1 490   android
9 使用Fragments / FragmentActivity保留跨活动重新创建的数据

我一直在浏览android文档和网络上的各种资源,但是我似乎无法让我的应用在整个活动重新创建期间保留数据(例如按返回按钮退出,然后从图标进入应用或任务管理器)。 我有3个类:主要的一个类(扩展FragmentActivity),一个片段和一个应在应用程序不活动时在后台运行的类,创建活动后, ...

10 android片段在onDestroy之后重新创建 - FragmentManagerState ClassNotFound

我正在使用带有3个片段的viewpager进行活动。 在启动选择图像后,调用onactivityResult但是 启动器活动被销毁并再次创建。 (我已经开启了不要保留任何活动,开发者设置。) 现在问题是在创建活动之后,还会再次创建片段(通过日志观察) 这将显示在 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM