关于Android远程进程导致程序代码多次执行问题
关于现象
遇到一个项目:核心功能的异步初始化需要在Application中添加,需要添加远程服务做主程序状态监控。出现的现象是:远程服务中也会有核心功能的打印输出。这样会对自由产生浪费,而且针对一些只能单次绑定的功能会出现主程序中莫名掉线的问题。代码示例:
public class SampleApplication extends Application {
private static final String TAG = "SampleApplication";
@Override
public void onCreate() {
super.onCreate();
String processName = getProcessName(this);
Log.d(TAG, processName + " onCreate");
coreFun();
}
//替代核心初始化
private void coreFun() {
new Thread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "run core fun!");
}
}).start();
}
//获取进程名称
private String getProcessName(Context context) {
int pid = android.os.Process.myPid();
ActivityManager mActivityManager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager
.getRunningAppProcesses()) {
if (appProcess.pid == pid) {
return appProcess.processName;
}
}
return "";
}
}
public class SampleRemoteService extends Service {
private static final String TAG = "SampleRemoteService";
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
}
输出结果:
主进程:
D/SampleApplication: com.wissen.test_remote_service onCreate
D/SampleApplication: run core fun!
远程服务进程:
D/SampleApplication: com.wissen.test_remote_service:remote onCreate
D/SampleApplication: run core fun!
D/SampleRemoteService: onCreate
两个进程都有执行核心函数,这与我们对远程服务的设计是不相符的。我们设计远程服务就是执行单一功能,用于监听主进程状态。所以需要对此现象进行调整。
关于Android远程服务
作为Android四大组件之一,Service的用法还是很常见的,Service分为本地服务和远程服务。
本地程序附属于主进程,主进程结束的话本地服务也会结束。本地服务具有节省资源,通信方便的优点。他通常可用于后台音乐播放等。
而远程服务是一个独立进程。生命周期跟主程序无相关性。远程服务由于是独立进程,所以相对来说更耗费资源,通讯也相对麻烦。可以用到AIDL进行进程间通信,可以与不同进程通信(包括外部app)。
远程服务如何执行
由于远程服务为独立进程,那么他和主进程一样也有程序入口。我们都知道主程序的入口为Application。但是我们却没有为远程服务添加Application类,所以远程服务与主程序公用Application。他也是调用Application的方法。
为何会因为远程服务导致程序功能多重执行
因为远程进程与主进程一样从Application开始创建,所以他与主进程一样会跑完Application里面的代码。这就是会导致在Application中添加的逻辑会被所有远程服务执行。其实大部分情况执行了并不会产生什么影响。因为大部分在Application里面执行的内容都是一次性的,代码执行结束之后任务就完成了,不会保留线程或者不会有对外部的状态抢占。但是我们的项目目前有针对服务器的长连接,单个设备保持单个连接,所以出现设备无缘无故掉线的状态才暴露出该问题。
如何避免程序功能多次执行
避免的方式有两种:
不在Application中添加混合的逻辑
该方法顾名思义就是使用默认的Application就行了,在入口Activity中执行最早需要执行的代码
通过代码过滤的方式让不同的进程执行不同代码块
通过判断进程名称就可以过滤让进程执行不同的代码块
在Application的onCreate方法中添加如下代码:
if (processName.contains(":remote")){
return;
}
添加后执行效果:
主进程:
D/SampleApplication: com.wissen.test_remote_service onCreate
D/SampleApplication: run core fun!
远程服务进程:
D/SampleApplication: com.wissen.test_remote_service:remote onCreate
D/SampleRemoteService: onCreate