问题描述
期望行为:退出插件时(即不使用时)将插件卸载——这样才满足插件化需求。
问题:为了解决插件不正常卸载的问题 ,在断连的时候强制pm clear 插件会导致宿主也自动关闭了,进而引起内存泄漏。
错误代码
@Override
public void onPluginDisconnected(IPluginUi plugin) {
if (mPlugin == plugin) mPlugin = null;//判断是否同一对象(内存地址相同)
Log.d(PLUGIN_TAG,"onPluginDisconnected " + plugin);
String pkgName = "com.tool.plugin";
try {
Runtime runtime = Runtime.getRuntime();
runtime.exec("pm clear " + pkgName);
Log.d(PLUGIN_TAG,"onPluginDisconnected: runtime execute pm clear " + pkgName);
} catch (Exception e) {
Log.d(PLUGIN_TAG, "Error while onPluginDisconnected " + e);
}
}
日志分析
原因:由于在Activity生命周期结束时未正确解除绑定的ServiceConnection引起的ServiceConnection内存泄漏。
07-05 07:42:57.480 17441 17441 D PluginListener: onPluginDisconnected: runtime execute pm clear com.tool.plugin
07-05 07:42:57.482 1358 5599 V ActivityTaskManager: Make invisible? ActivityRecord{8eff59a u0 com.android.settings/.Settings t34} finishing=false state=STOPPED containerShouldBeVisible=true behindFullyOccludedContainer=true mLaunchTaskBehind=false
07-05 07:42:57.482 1358 5599 V ActivityTaskManager: Already invisible: ActivityRecord{8eff59a u0 com.android.settings/.Settings t34}
07-05 07:42:57.482 1358 5599 V ActivityTaskManager: ensureActivitiesVisible behind ActivityRecord{4c28d0d u0 com..android.launcher/.uioverrides.QuickstepLauncher t7}
07-05 07:42:57.482 17441 17441 E ActivityThread: Activity com.android.settings.SubSettings has leaked ServiceConnection com.android.settings.network.telephony.NetworkPreferenceCategoryController$1@9e05856 that was originally bound here
07-05 07:42:57.482 17441 17441 E ActivityThread: android.app.ServiceConnectionLeaked: Activity com.android.settings.SubSettings has leaked ServiceConnection com.android.settings.network.telephony.NetworkPreferenceCategoryController$1@9e05856 that was originally bound here
从日志能学习Actvity线程执行的相关生命周期流程。
07-05 07:42:57.482 17441 17441 E ActivityThread: at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:2113)
07-05 07:42:57.482 17441 17441 E ActivityThread: at android.app.LoadedApk.getServiceDispatcherCommon(LoadedApk.java:1985)
07-05 07:42:57.482 17441 17441 E ActivityThread: at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:1964)
07-05 07:42:57.482 17441 17441 E ActivityThread: at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:2141)
07-05 07:42:57.482 17441 17441 E ActivityThread: at android.app.ContextImpl.bindService(ContextImpl.java:2017)
07-05 07:42:57.482 17441 17441 E ActivityThread: at android.content.ContextWrapper.bindService(ContextWrapper.java:863)
07-05 07:42:57.482 17441 17441 E ActivityThread: at com.android.settings.network.telephony.NetworkPreferenceCategoryController.bindNetworkQueryService(NetworkPreferenceCategoryController.java:285)
07-05 07:42:57.482 17441 17441 E ActivityThread: at com.android.settings.network.telephony.NetworkPreferenceCategoryController.registerNetworkQueryService(NetworkPreferenceCategoryController.java:171)
07-05 07:42:57.482 17441 17441 E ActivityThread: at com.android.settings.network.telephony.MobileNetworkSettings.onCreate(MobileNetworkSettings.java:514)
07-05 07:42:57.482 17441 17441 E ActivityThread: at androidx.fragment.app.Fragment.performCreate(Fragment.java:3094)
07-05 07:42:57.482 17441 17441 E ActivityThread: at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:504)
07-05 07:42:57.482 17441 17441 E ActivityThread: at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:268)
07-05 07:42:57.482 17441 17441 E ActivityThread: at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1943)
07-05 07:42:57.482 17441 17441 E ActivityThread: at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1839)
07-05 07:42:57.482 17441 17441 E ActivityThread: at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1782)
07-05 07:42:57.482 17441 17441 E ActivityThread: at androidx.fragment.app.FragmentManager.executePendingTransactions(FragmentManager.java:641)
07-05 07:42:57.482 17441 17441 E ActivityThread: at com.android.settings.SettingsActivity.switchToFragment(SettingsActivity.java:799)
代码解读
Fragment创建的时候,因为注册了网络相关服务,而pm clear时没有取消服务出错导致内存泄漏。
package com.android.settings.network.telephony;
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class MobileNetworkSettings extends AbstractMobileNetworkSettings implements
MobileNetworkRepository.MobileNetworkCallback {
@Override
public void onCreate(Bundle icicle) {
final TelephonyStatusControlSession session =
setTelephonyAvailabilityStatus(getPreferenceControllersAsList());
super.onCreate(icicle);
final Context context = getContext();
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mTelephonyManager = context.getSystemService(TelephonyManager.class)
.createForSubscriptionId(mSubId);
session.close();
//安装插件并监听
Log.d(LOG_TAG,"onPluginConnected during onCreate ");
PluginManagerWrapper.getInstance(context).addPluginListener(mPluginListener,IPluginUi.class
,true);
onRestoreInstance(icicle);
//注册了服务
use(OpNetworkPreferenceCategoryController.class).registerNetworkService();
}
}