初始化Android应用程序的正确方法是什么?

时间:2018-07-16 21:21:11

标签: android

问题:在准备好使用我的应用之前,我需要在每次启动时运行一些代码。

起初,我尝试在专门的活动中做到这一点。

AndroidManifest.xml

<activity android:name=".MainActivity" />

<activity android:name=".StarterActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

AppLoader.java

public class AppLoader {

    private static Object someInstance;

    public static void load(Runnable onCompleteCallback) {
        try {
            someInstance = new Object();

            //potentially long operation to initialize the app
            Thread.sleep(5000);

            onCompleteCallback.run();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public static void checkInitialized() {
        if (someInstance == null) {
            throw new RuntimeException("Not initialized");
        }
    }
}

StarterActivity.java

public class StarterActivity extends AppCompatActivity {

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

        AppLoader.load(() -> {
            MainActivity.start(this);
            finish();
        });
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    public static void start(Context context) {
        Intent starter = new Intent(context, MainActivity.class);
        context.startActivity(starter);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        AppLoader.checkInitialized();
    }
}

如果该应用是通过启动器图标冷启动的,但在所有其他情况下崩溃,则可以正常工作。重现问题的简单方法:

  1. 转到设备上的开发人员设置,并将“后台进程限制”设置为“无后台进程”
  2. 打开应用
  3. 打开其他应用
  4. 再次打开应用。结果:它崩溃了。

这是一篇描述类似问题的文章:Android process death — and the (big) implications for your app

可能的解决方案:

  1. 延迟加载/反应方式。我尝试尽可能多地使用它,但是在用户与应用程序进行交互之前,总是需要以阻塞的方式运行一些代码,所以这还不够。
  2. 将所有这些代码放入App.onCreate()中。这可能适用于小型应用程序,但是我已经看到大型应用程序需要5到10秒的时间进行初始化,并且我怀疑它们为此使用了onCreate()。可能的弊端:Android Vitals中的ANR和/或过多的启动时间?
  3. 检查应用是否已在BaseActivity中初始化,但这将需要阻止onCreate或手动管理生命周期回调,但这听起来不是个好主意。

那么,每次启动应用程序时运行一些代码的正确方法是什么?

注意:通常StarterActivity将是一个初始屏幕,AppLoader将被注入,等等,但是为了简单起见,我省略了它。

3 个答案:

答案 0 :(得分:0)

AndroidManifest.xml

Sub GetInfo()
    Const Url$ = "https://www.austrade.gov.au/SupplierDetails.aspx?ORGID=ORG0120000508&folderid=1736"
    Dim Http As New XMLHTTP60, rxp As New RegExp

    With Http
        .Open "GET", Url, False
        .send
    End With

    With rxp
        .Pattern = "Company Name:(\s[\w\s]+)"
        If .Execute(Http.responseText).Count > 0 Then
            [A1] = .Execute(Http.responseText)(0).SubMatches(0)
        End If

        .Pattern = "Phone:(\s\+[\d\s]+)"
        If .Execute(Http.responseText).Count > 0 Then
            [B1] = .Execute(Http.responseText)(0).SubMatches(0)
        End If

        .Pattern = "Fax:(\s\+[\d\s]+)"
        If .Execute(Http.responseText).Count > 0 Then
            [C1] = .Execute(Http.responseText)(0).SubMatches(0)
        End If
    End With
End Sub

AppLoader.java

<application
    android:name=".AppLoader"

更新 -在启动画面上使用public class AppLoader extends Application { private static Object someInstance; @Override public void onCreate() { super.onCreate(); // DO YOUR STUFF } }

Handler

答案 1 :(得分:0)

您的应用抛出了您在AppLoader.checkInitialized()方法中设置的RuntimeException,因为当应用进入后台并被系统杀死时,someInstance对象将丢失其状态(因为您已将设备设置为保持零后台线程)。因此,当您尝试重新打开应用程序时,系统将直接启动MainActivity(而不是StarterActivity),因为它正在尝试恢复其先前状态。但是变量无法恢复,甚至静态变量也无法恢复。

因此,如果您在MainActivity上需要Object SomeInstance,则应将其实例化集成到MainActivitie的生命周期中,并覆盖诸如onSavedInstanceState,onRestoreInstanceState等之类的方法,以在您的应用被系统杀死后正确处理并重新加载该对象。 / p>

看看这个https://developer.android.com/guide/components/activities/activity-lifecycle

答案 2 :(得分:0)

如果有人感兴趣,我最终只是在需要时将用户重定向到StarterActivity,以确保每次启动都执行必要的代码。

public abstract class BaseActivity extends AppCompatActivity {

    private boolean isCreated;

    @Override
    protected final void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (!appLoader.isLoaded()) {
            StarterActivity.start(this);
            finish();
            return;
        }

        onCreateActivity(savedInstanceState);
        isCreated = true;
    }

    protected void onCreateActivity(@Nullable Bundle savedInstanceState) {
    }

    @Override
    protected final void onDestroy() {
        super.onDestroy();
        if (isCreated) {
            onDestroyActivity();
        }
    }

    protected void onDestroyActivity() {
    }

}

所有活动都扩展了BaseActivity(StarterActivity除外),并覆盖了onCreateActivity / onDestroyActivity而不是onCreate / onDestroy。