简介
在多进程开发的时候我们可能需要知道当前进程是主进程还是子进程,这是就需要我们取获取到当前所处进程的名字了。
- 以下是获取到进程名字的几种方式,以及区别和对比
获取方式
使用ActivityManager获取
- 该方式也是我们能查阅资料看见最多的实现方式
- 代码如下
object ProcessUtils {
/**
* 通过ActivityManager获取到进程名字
*/
fun getCurrentProcessName(context:Context):String?{
var myPid = Process.myPid()
var activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
var runningAppProcesses = activityManager.runningAppProcesses
if (!runningAppProcesses.isNullOrEmpty()){
runningAppProcesses.forEach {
if (it.pid == myPid){
return it.processName
}
}
}
return null
}
}
- 测试代码如下
class AppApplication : Application() {
init {
//初始化打印
//initLog()
ApplicationController.init(this, true)
}
override fun onCreate() {
super.onCreate()
initARouter()
ApplicationController.transformOnCreate()
if (ProcessUtils.getCurrentProcessName(this) == BuildConfig.APPLICATION_ID){
DQLog.d("init main application")
}
}
}
- 打印结果如下
2020-10-19 22:43:38.154 24073-24073/com.dashingqi.mvvmcomponent D/AppApplication: init main application
分析一下
// activityManager.runningAppProcesses ---> ActivityManager # getRunningAppProcess()
public List<RunningAppProcessInfo> getRunningAppProcesses() {
try {
return getService().getRunningAppProcesses();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
// 其中getService() ---> IActivityManager,而IActivityManager是一个AIDL文件,作为和ActivytMangerServie通信,也就是跨进程通信发生了。
- 所以经过以上分析,可以得出有跨进程通信,就会有响应的耗时
- 再者我们是通过获取到所以运行的进程,然后一个一个比对,这样循环调用也会有相应的性能损耗。
- 以上使用ActivityManager获取进程名称是属于常规操作了,下面使用下骚操作。
API28 新增方法 Application # getProcessName()
- 代码如下
/**
* AP28以上才能使用
* 直接获取到进程名称,不会有跨进程,反射的耗时操作
*/
fun getCurrentProcessNameOnP():String?{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
return Application.getProcessName()
}
return null
}
- 测试代码
override fun onCreate() {
super.onCreate()
initARouter()
ApplicationController.transformOnCreate()
var name = ProcessUtils.getCurrentProcessName(this)
Log.d(TAG,"name $name")
var pName = ProcessUtils.getCurrentProcessNameOnP()
Log.d(TAG,"pName === $pName")
if (ProcessUtils.getCurrentProcessName(this) == BuildConfig.APPLICATION_ID){
Log.d(TAG,"init main application")
}
}
- 打印结果如下
2020-10-19 23:03:31.400 26933-26933/com.dashingqi.mvvmcomponent D/AppApplication: pName === com.dashingqi.mvvmcomponent
分析一下
// Application # getProcessName() ----> ActivityThread.currentProcessName()
public static String currentProcessName() {
ActivityThread am = currentActivityThread();
return (am != null && am.mBoundApplication != null)
? am.mBoundApplication.processName : null;
}
//我们可以看到 currentProcessName() 是 public static
// 但是我们看到注解描述 ActivityThread 是@hide
//那么有没有其他的操作可以搞一下呢?
- 通过反射调用ActivityThread中的currentProcessName()
fun getCurrentProcessNameByAT(): String? {
var processName: String? = null
try {
val declaredMethod: Method = Class.forName("android.app.ActivityThread", false, Application::class.java.classLoader)
.getDeclaredMethod("currentProcessName")
declaredMethod.isAccessible = true
val invoke: Any = declaredMethod.invoke(null)
if (invoke is String) {
processName = invoke
}
} catch (e: Throwable) {
e.printStackTrace()
}
return processName
}
// 执行结果如下
// 2020-10-19 23:21:36.487 28594-28594/com.dashingqi.mvvmcomponent D/AppApplication: atName == com.dashingqi.mvvmcomponent
- 该方法是采用了反射调用了,并没有进行IPC通信,所以耗时通常不会比第一个要长
进行一下耗时的比较
- 测试代码
val nameStart = SystemClock.elapsedRealtimeNanos()
var name = ProcessUtils.getCurrentProcessName(this)
Log.d(TAG,"getCurrentProcessName cost == ${SystemClock.elapsedRealtimeNanos()-nameStart}")
val pNameStart = SystemClock.elapsedRealtimeNanos()
var pName = ProcessUtils.getCurrentProcessNameOnP()
Log.d(TAG,"getCurrentProcessNameOnP cost == ${SystemClock.elapsedRealtimeNanos() - pNameStart}")
val atNameStart = SystemClock.elapsedRealtimeNanos()
var atName = ProcessUtils.getCurrentProcessNameByAT()
Log.d(TAG,"getCurrentProcessNameByAT cost == ${SystemClock.elapsedRealtimeNanos()-atNameStart}")
- 运行结果
2020-10-19 23:31:24.867 29657-29657/com.dashingqi.mvvmcomponent D/AppApplication: getCurrentProcessName cost == 641875
2020-10-19 23:31:24.867 29657-29657/com.dashingqi.mvvmcomponent D/AppApplication: getCurrentProcessNameOnP cost == 28229
2020-10-19 23:31:24.867 29657-29657/com.dashingqi.mvvmcomponent D/AppApplication: getCurrentProcessNameByAT cost == 119792
总的说来,直接获取要好于反射的方式,放射的方式要好于IPC方式
网友评论