Skip to content

Commit

Permalink
fix(core.runtime): ActivityLifecycleCallbacks与其Wrapper映射Map采用弱引用实现
Browse files Browse the repository at this point in the history
避免原本采用静态域sAllHolders强引用持有Wrapper带来的内存泄漏风险。
  • Loading branch information
shifujun committed Mar 23, 2022
1 parent d2f3995 commit bbf317f
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ import com.tencent.shadow.core.loader.managers.ComponentManager.Companion.CM_CLA
import com.tencent.shadow.core.loader.managers.ComponentManager.Companion.CM_EXTRAS_BUNDLE_KEY
import com.tencent.shadow.core.loader.managers.ComponentManager.Companion.CM_LOADER_BUNDLE_KEY
import com.tencent.shadow.core.loader.managers.ComponentManager.Companion.CM_PART_KEY
import com.tencent.shadow.core.runtime.*
import com.tencent.shadow.core.runtime.MixResources
import com.tencent.shadow.core.runtime.PluginActivity
import com.tencent.shadow.core.runtime.PluginManifest
import com.tencent.shadow.core.runtime.ShadowActivity
import com.tencent.shadow.core.runtime.container.HostActivityDelegate
import com.tencent.shadow.core.runtime.container.HostActivityDelegator

Expand Down Expand Up @@ -289,7 +292,7 @@ open class ShadowActivityDelegate(private val mDI: DI) : GeneratedShadowActivity
pluginActivity: ShadowActivity,
pluginSavedInstanceState: Bundle?
) {
ShadowActivityLifecycleCallbacks.Holder.notifyPluginActivityPreCreated(
mPluginApplication.mActivityLifecycleCallbacksHolder.notifyPluginActivityPreCreated(
pluginActivity,
pluginSavedInstanceState
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,18 @@ static PluginActivity get(PluginContainerActivity pluginContainerActivity) {

ComponentName mCallingActivity;

private ShadowActivityLifecycleCallbacks.Holder lifecycleCallbacksHolder;

public void registerActivityLifecycleCallbacks(
ShadowActivityLifecycleCallbacks callback) {
lifecycleCallbacksHolder.registerActivityLifecycleCallbacks(this, callback);
mPluginApplication.mActivityLifecycleCallbacksHolder.registerActivityLifecycleCallbacks(
callback, this, hostActivityDelegator
);
}

public void unregisterActivityLifecycleCallbacks(
ShadowActivityLifecycleCallbacks callback) {
lifecycleCallbacksHolder.unregisterActivityLifecycleCallbacks(callback);
mPluginApplication.mActivityLifecycleCallbacksHolder.unregisterActivityLifecycleCallbacks(
callback, this, hostActivityDelegator
);
}

public final void setHostContextAsBase(Context context) {
Expand All @@ -65,7 +67,6 @@ public final void setHostContextAsBase(Context context) {
public void setHostActivityDelegator(HostActivityDelegator delegator) {
super.hostActivityDelegator = delegator;
hostActivityDelegator = delegator;
lifecycleCallbacksHolder = new ShadowActivityLifecycleCallbacks.Holder(delegator);
}

public void setPluginApplication(ShadowApplication pluginApplication) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
import com.tencent.shadow.core.runtime.container.HostActivityDelegator;
import com.tencent.shadow.core.runtime.container.PluginContainerActivity;

import java.util.HashMap;
import java.util.HashSet;
import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

public interface ShadowActivityLifecycleCallbacks {

Expand Down Expand Up @@ -96,6 +98,7 @@ class Wrapper implements Application.ActivityLifecycleCallbacks {

final ShadowActivityLifecycleCallbacks shadowActivityLifecycleCallbacks;
final Object runtimeObject;
private boolean isRegistered;

public Wrapper(ShadowActivityLifecycleCallbacks shadowActivityLifecycleCallbacks, Object runtimeObject) {
this.shadowActivityLifecycleCallbacks = shadowActivityLifecycleCallbacks;
Expand Down Expand Up @@ -354,90 +357,93 @@ private boolean checkOwnerActivity(PluginActivity activity) {
}
}

/**
* ShadowActivity和ShadowApplication共用的ActivityLifecycleCallbacks逻辑。
* 用一个Map将ActivityLifecycleCallbacks映射成ShadowActivityLifecycleCallbacks。
* 同时,持有所有的有注册ActivityLifecycleCallbacks的Holder,
* 提供通知所有callbacks onPluginActivityPreCreated事件的方法。
*/
class Holder {
final private static Set<Holder> sAllHolders = new HashSet<>();

final private HostActivityDelegator delegator;
final private Application application;

final private Map<ShadowActivityLifecycleCallbacks,
Wrapper>
mActivityLifecycleCallbacksMap = new HashMap<>();
WeakReference<Wrapper>>
mShadowActivityLifecycleCallbacksWrapperMap = new WeakHashMap<>();

public Holder(Object hostActivityDelegatorOrApplication) {
if (hostActivityDelegatorOrApplication instanceof HostActivityDelegator) {
this.delegator = (HostActivityDelegator) hostActivityDelegatorOrApplication;
this.application = null;
} else {
this.delegator = null;
this.application = (Application) hostActivityDelegatorOrApplication;
}
}
/**
* 针对业务代码自己不持有ActivityLifecycleCallbacks的情况,
* 无法通过mShadowActivityLifecycleCallbacksWrapperMap获取所有wrapper,
* 需要特别记录所有wrapper。
* <p>
* 采用弱引用以便不影响Wrapper原本的GC时机,Wrapper至少被系统持有。
* <p>
* GuardedBy mShadowActivityLifecycleCallbacksWrapperMap
*/
final private Map<ShadowActivityLifecycleCallbacks.Wrapper, Object>
mAllShadowActivityLifecycleCallbackWrappers = new WeakHashMap<>();

private void register(Application.ActivityLifecycleCallbacks callbacks) {
if (delegator != null) {
delegator.registerActivityLifecycleCallbacks(callbacks);
} else {
assert application != null;
application.registerActivityLifecycleCallbacks(callbacks);
}
}
public void notifyPluginActivityPreCreated(ShadowActivity pluginActivity,
Bundle savedInstanceState) {
synchronized (mShadowActivityLifecycleCallbacksWrapperMap) {
//onPluginActivityPreCreated中可能会再次调用registerActivityLifecycleCallbacks,
//进而修改mAllShadowActivityLifecycleCallbackWrappers,
//因此需要先复制出待通知的callback,再通知。
List<Wrapper> copiedWrappers = new LinkedList<>();
Set<Wrapper> wrappers
= mAllShadowActivityLifecycleCallbackWrappers.keySet();
for (ShadowActivityLifecycleCallbacks.Wrapper wrapper : wrappers) {
// wrapper是弱引用持有的,需要二次验证其是否处于register状态
if (wrapper != null && wrapper.isRegistered) {
copiedWrappers.add(wrapper);
}
}

private void unregister(Application.ActivityLifecycleCallbacks callbacks) {
if (delegator != null) {
delegator.unregisterActivityLifecycleCallbacks(callbacks);
} else {
assert application != null;
application.unregisterActivityLifecycleCallbacks(callbacks);
for (ShadowActivityLifecycleCallbacks.Wrapper wrapper : copiedWrappers) {
wrapper.onPluginActivityPreCreated(pluginActivity, savedInstanceState);
}
}
}

public void registerActivityLifecycleCallbacks(
Object caller,
ShadowActivityLifecycleCallbacks callback) {
synchronized (sAllHolders) {
final ShadowActivityLifecycleCallbacks.Wrapper wrapper
= new ShadowActivityLifecycleCallbacks.Wrapper(callback, caller);
mActivityLifecycleCallbacksMap.put(callback, wrapper);
register(wrapper);
sAllHolders.add(this);
private ShadowActivityLifecycleCallbacks.Wrapper shadowActivityLifecycleCallbacksToWrapper(
ShadowActivityLifecycleCallbacks callbacks,
Object caller
) {
if (callbacks == null) {
return null;
}
synchronized (mShadowActivityLifecycleCallbacksWrapperMap) {
ShadowActivityLifecycleCallbacks.Wrapper wrapper;
WeakReference<ShadowActivityLifecycleCallbacks.Wrapper> weakReference
= mShadowActivityLifecycleCallbacksWrapperMap.get(callbacks);
wrapper = weakReference == null ? null : weakReference.get();
if (wrapper == null) {
wrapper = new ShadowActivityLifecycleCallbacks.Wrapper(callbacks, caller);
mShadowActivityLifecycleCallbacksWrapperMap.put(callbacks,
new WeakReference<>(wrapper));
mAllShadowActivityLifecycleCallbackWrappers.put(wrapper, null);
}
return wrapper;
}
}

public void unregisterActivityLifecycleCallbacks(
ShadowActivityLifecycleCallbacks callback) {
synchronized (sAllHolders) {
final Application.ActivityLifecycleCallbacks activityLifecycleCallbacks
= mActivityLifecycleCallbacksMap.get(callback);
if (activityLifecycleCallbacks != null) {
unregister(activityLifecycleCallbacks);
mActivityLifecycleCallbacksMap.remove(callback);
}
if (mActivityLifecycleCallbacksMap.isEmpty()) {
sAllHolders.remove(this);
}
void registerActivityLifecycleCallbacks(ShadowActivityLifecycleCallbacks callback,
Object caller,
Object hostActivityDelegatorOrApplication) {
Wrapper wrapper = shadowActivityLifecycleCallbacksToWrapper(callback, caller);
wrapper.isRegistered = true;
if (hostActivityDelegatorOrApplication instanceof HostActivityDelegator) {
((HostActivityDelegator) hostActivityDelegatorOrApplication)
.registerActivityLifecycleCallbacks(wrapper);
} else {
((Application) hostActivityDelegatorOrApplication)
.registerActivityLifecycleCallbacks(wrapper);
}
}

public static void notifyPluginActivityPreCreated(ShadowActivity pluginActivity, Bundle savedInstanceState) {
synchronized (sAllHolders) {
//onPluginActivityPreCreated中可能会再次调用registerActivityLifecycleCallbacks,
//进而修改sAllHolders和mActivityLifecycleCallbacksMap,
//因此需要先复制出待通知的callback,再通知。
Holder[] holders = sAllHolders.toArray(new Holder[0]);
for (Holder holder : holders) {
Wrapper[] wrappers = holder.mActivityLifecycleCallbacksMap.values().toArray(new Wrapper[0]);
for (ShadowActivityLifecycleCallbacks.Wrapper wrapper : wrappers) {
wrapper.onPluginActivityPreCreated(pluginActivity, savedInstanceState);
}
}
void unregisterActivityLifecycleCallbacks(ShadowActivityLifecycleCallbacks callback,
Object caller,
Object hostActivityDelegatorOrApplication) {
Wrapper wrapper = shadowActivityLifecycleCallbacksToWrapper(callback, caller);
wrapper.isRegistered = false;
if (hostActivityDelegatorOrApplication instanceof HostActivityDelegator) {
((HostActivityDelegator) hostActivityDelegatorOrApplication)
.unregisterActivityLifecycleCallbacks(wrapper);
} else {
((Application) hostActivityDelegatorOrApplication)
.unregisterActivityLifecycleCallbacks(wrapper);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,28 @@ public class ShadowApplication extends ShadowContext {

private ShadowAppComponentFactory mAppComponentFactory;

final public ShadowActivityLifecycleCallbacks.Holder mActivityLifecycleCallbacksHolder
= new ShadowActivityLifecycleCallbacks.Holder();

public boolean isCallOnCreate;

@Override
public Context getApplicationContext() {
return this;
}

private ShadowActivityLifecycleCallbacks.Holder lifecycleCallbacksHolder;

public void registerActivityLifecycleCallbacks(
ShadowActivityLifecycleCallbacks callback) {
lifecycleCallbacksHolder.registerActivityLifecycleCallbacks(this, callback);
mActivityLifecycleCallbacksHolder.registerActivityLifecycleCallbacks(
callback, this, mHostApplication
);
}

public void unregisterActivityLifecycleCallbacks(
ShadowActivityLifecycleCallbacks callback) {
lifecycleCallbacksHolder.unregisterActivityLifecycleCallbacks(callback);
mActivityLifecycleCallbacksHolder.unregisterActivityLifecycleCallbacks(
callback, this, mHostApplication
);
}

public void onCreate() {
Expand Down Expand Up @@ -147,8 +152,6 @@ public void unregisterOnProvideAssistDataListener(Application.OnProvideAssistDat
public void setHostApplicationContextAsBase(Context hostAppContext) {
super.attachBaseContext(hostAppContext);
mHostApplication = (Application) hostAppContext;
lifecycleCallbacksHolder
= new ShadowActivityLifecycleCallbacks.Holder(mHostApplication);
}

public void setBroadcasts(PluginManifest.ReceiverInfo[] receiverInfos) {
Expand Down

0 comments on commit bbf317f

Please sign in to comment.