Android在调用super.OnCreate()之前停止onCreate()中的活动

10

我正在创建一个带有片段的导航抽屉活动应用程序。在每次冷启动应用程序时,我执行一些初始化代码,其中加载以下内容:

  • 用户会话(如果用户已登录或未登录)
  • 注册Retrofit服务
  • 从服务器获取一些数据以继续启动应用程序。

这是我的应用程序在进行冷启动时的流程:

  • 启动MainActivity并验证用户会话。
  • 如果会话有效,则打开CoreActivity
  • 否则,打开LoginActivity

当应用程序在一段时间不活动后被带到前台时,Android 尝试重新启动当前活动。这意味着我的初始化代码被绕过,并执行了CoreActivity.onCreate()

MainActivity外,所有我的活动都扩展了以下超级活动:

public abstract class MasterActivity extends AppCompatActivity {

@Override
protected final void onCreate(Bundle savedInstanceState) {
    this.supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    if (!CrmContext.getInstance().verifyContextSet(this)) {
        return;
    }
    super.onCreate(savedInstanceState);
    onCreateAfterContext(savedInstanceState);
}

在CrmContext中:

public boolean verifyContextSet(final Context context) {
    boolean isContextSet = applicationContext != null;
    if (isContextSet) {
        return true;
    }
    Intent intent = new Intent(context, MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    context.startActivity(intent);
    return false;
}

verifyContextSet()中,我正在进行一些检查,以确保应用程序已正确加载。如果用户会话未正确加载,则出现问题。

我的问题:

如果将应用程序置于前台,则会执行CoreActivity.onCreate()并且verifyContextSet()返回false。在这种情况下,我想取消创建CoreActivity并再次打开MainActivity

当我在调用super.onCreate()之前执行verifyContextSet()时,我会得到以下异常:

android.util.SuperNotCalledException: Activity {nl.realworks.crm/nl.realworks.crm.view.CoreActivity} did not call through to super.onCreate() at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2287) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391) at android.app.ActivityThread.access$800(ActivityThread.java:151) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)

我尝试先执行super.onCreate(),但是这意味着活动内部的Fragment会首先被创建。这意味着我的Fragment会在verifyContextSet()被执行之前重新创建。

因此,如果我在调用super.onCreate()之前尝试cancel()/finish() onCreate(),那么我会得到SuperNotCalledException。如果我先执行super.onCreate(),则会初始化Fragment,而这在verifyContextSet()返回false时是不允许的。

我想要做以下事情:

  • 将应用程序置于前台
  • 检查应用程序是否已初始化
  • 如果没有,则finish()当前activity并重新启动应用程序以打开MainActivity


我已经调整了我的问题,以使事情更加清晰。 - com2ghz
有人解决过这个问题吗? - Bhargav
@com2ghz 在我看来,不调用 super 是一种不好的方法。对我来说,这听起来像是你想要检查活动的启动模式。你可能想使用 <activity android:launchMode= "singleInstance" /> - longi
1
我认为这里的问题不在于如何防止活动恢复(已经概述了),而是整个想法架构不正确,OP现在正在与Android框架作斗争,以适应这个要求。 - Martin Marconcini
我通过不在片段的 onAttach() 回调中执行任何操作来解决了我的问题,因为当从进程死亡中恢复时,onAttach() 将从 FragmentActivityonCreate() 中调用。 - Bhargav
显示剩余3条评论
5个回答

1
将您的检查/验证代码放在一个Application子类中。
public class MyApp extends Application {
//in your oncreate create sessions etc.

现在,无论是否重新启动MainActivity,您都已经进行了验证。
注意:Application类的onCreate()是在任何其他内容之前运行的。

我尝试过这个,但它仍然继续启动先前打开的Activity。我该如何防止重新启动上一个Activity? - com2ghz

1
你需要做的是将你的onCreate写成这样:
super.onCreate();
if(<activity is not valid>) {
   startAnotherActivity()
   finish()
   return;
}

这将确保除onDestroy之外的任何其他活动生命周期方法都不会被调用,即onResume、onPause、onStop、onStart。

0

我认为代码应该看起来像这样

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Your code

}

super.onCreate(savedInstanceState) 总是作为第一行。


2
当我这样做时,super.onCreate() 尝试在我的 verifyContextSet() 执行之前恢复/初始化 Fragment。 - com2ghz
@MikeM。在应用程序进入后台之前打开的上一个片段。我认为代码是无关紧要的,因为我想在我的片段加载之前进行检查。 - com2ghz
我已经将我的检查移动到Application.onCreate(),但我无法中断执行。它仍然试图恢复先前的Activity。 - com2ghz

0
您可以使用ViewModel和Observer。 基本上,只有在触发Observer时,您剩余的onCreate代码才会执行。

onResume {

    // THIS WILL TRIGGER THE OBSERVER
    viewModel._needVerification.value = true

}

onCreate {

    super.onCreate()

    ... CREATE VIEWMODEL

    // THIS NEEDED TO HANDLE RECREATED ACTIVITY CAUSE BY SCREEN ORIENTATION ETC
    viewModel._verificationFinished.value = false

    viewModel.needVerification.observe(this, Observer{

        if (it == true) {

            verifyContextSet(final Context context) {

                if (isContextSet) {

                    if (viewModel.verificationFinished.value != true) {

                        ... DO REMAINING ONCREATE CODE 

                        viewModel._verificationFinished.value = true

                    }

                } else {

                    Start MainActivity

                }

            }

        }

  })

}

不,你不需要这些。 - EpicPandaForce
1
我将单词“需要”更改为“可以”。 - nfl-x

0

不要仅从onCreate返回,您需要先完成Activity以停止触发其他初始化回调。

只需更改此代码

if (!CrmContext.getInstance().verifyContextSet(this)) {
    return;
}

转换成这个

if (!CrmContext.getInstance().verifyContextSet(this)) {
    finish();
    return;
}

不推荐在没有Return的情况下结束。 - Rahul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接