android:process 导致我的 MyApplication 的 onCreate 方法被调用两次。如何防止代码运行两次?



我知道,如果我在清单中使用android:process,那么扩展Application的类将被调用两次。一次,用于应用程序,第二次用于新进程。

问题是我在MyApplication(扩展应用程序(中有代码,不应该调用两次。我想有一个单独的进程,但我只希望MyApplication#onCreate中的代码每次加载运行一次。

我试着在Shared Preferences中设置一个标志,但它不起作用,可能是因为问题的不同过程

有什么想法吗?

根本原因

来自SharedPreferences文档:

注意:此类不支持跨多个进程使用。

这解释了SharePreferences不工作的原因。

解决方案1:使用上下文。MODE_MULTI_PROCESS,但在API 23级中已弃用

public static final int MODE_MULTI_PROCESS

此常量在API 23级中已弃用。

MODE_MULTI_PROCESS在某些版本的Android中不能可靠工作,而且没有提供任何调解机制跨进程的并发修改。应用程序不应尝试使用它。相反,他们应该使用一个明确的交叉过程诸如ContentProvider之类的数据管理方法。

解决方案2:使用ContentProvider

2.1.编写自己的ContentProvider

  • 我们只需要一种方法来存储一个布尔变量,该变量指示MyApplicationonCreate()方法是否是第一次调用的,使用此解决方案似乎效率低下

2.2.使用Android 中预定义的ContentProvider

  • 应用程序必须声明读/写外部存储权限,并请求运行时权限。顺便说一句,当用户第一次打开应用程序时,它会让他们感到困惑

解决方案3:我们可以使用以下流程来实现

  • 声明与应用程序在同一进程中运行的BroadcastReceiver。因为它们在同一个进程上运行,所以它们有相同的进程id。

  • 运行在单独进程(私有或全局(上的组件(活动、服务、接收器、提供者(,因此它们将具有不同的进程id。

实施

步骤1.创建一个从BoardcastReceiver扩展的类,名为AppReceiver

public class AppReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Messenger messenger = intent.getParcelableExtra(MyApplication.EXTRA_MESSENGER);
int processId = intent.getIntExtra(MyApplication.EXTRA_PROCESS_ID, -1);
boolean isOnCreateCalledFirstTime = processId == Process.myPid();
Message message = Message.obtain();
message.arg1 = isOnCreateCalledFirstTime ? 1 : 0;
try {
messenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}

步骤2.将该类添加到AndroidManifest.xml

<receiver
android:name=".AppReceiver"
android:enabled="true"
android:exported="true" />

步骤3.修改您的MyApplication

public class MyApplication extends Application {
public static final String EXTRA_MESSENGER = "EXTRA_MESSENGER";
public static final String EXTRA_PROCESS_ID = "EXTRA_PROCESS_ID";
@Override
public void onCreate() {
super.onCreate();
Intent intent = new Intent();
String pkg = getPackageName();
intent.setComponent(new ComponentName(pkg, pkg + ".AppReceiver"));
Handler handler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
boolean isOnCreateCalledFirstTime = msg.arg1 != 0;
if (isOnCreateCalledFirstTime) {
// TODO: First time onCreate() is called
} else {
// TODO: Next time onCreate() is called
}
return true;
}
});
Messenger messenger = new Messenger(handler);
intent.putExtra(EXTRA_MESSENGER, messenger);
intent.putExtra(EXTRA_PROCESS_ID, Process.myPid());
sendBroadcast(intent);
}
}

最新更新