-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ShadowContext中unregisterReceivery可能有问题 #865
Comments
设计如此。而且这里是WrapperMap,即便有bug,影响也应该是内存泄漏。不应该出现对应Wrapper没有注册的情况。 WrapperMap保存的是receiver和wrapper两个对象的映射关系,这个映射关系和receiver是否被注册到系统了没有关系。 最好还是在sample上复现一下有问题的场景,否则我暂时理解不了bug是怎么产生的。 |
之前那样写只会执行 super.unregisterReceiver(wrapper);中而不会执行super.unregisterReceiver(receiver);。我先在test里复现下,实际工程使用中就是这样的。改了866号PR后就不会崩了 |
我用示例中复出不出来>_<,场景就是动态广播在dialog中注册,activity中有多个dialog,dialog中的广播是onshowlistener中注册,ondismisslistener中反注册。使用示例中的代码虽然不会崩了。dialog使用的都是同一个context引用,也就是同一个mReceiverWrapperMap,这样activity只要不销毁,mReceiverWrapperMap的长度只增不减。我猜测我之前那个崩是因为某个原因没有把receiver添加到mReceiverWrapperMap中,然后反注册时调用了receiverToWrapper方法,然后又往mReceiverWrapperMap里添加了一个,然后反注册了BroadcastReceiverWrapper,而非原始receiver |
receiver的注册和反注册可能由不同的context完成。 fixup! d2f3995 fix Tencent#865
我猜应该是这个错误导致的:#867 可以测一下能不能复现问题了。 |
直接运行sample-host不崩吗? 我这运行sample-host然后点启动插件就崩了(使用#867 |
添加了一个 82fd262 修复了 |
好了,另外反注册时mReceiverWrapperMap不移除一下么,要不然Map长度会一直增长 |
不需要。这个map跟receiver是否注册了没有关系。它是弱引用实现的,只要有其他强引用,就说明还有可能需要转换wrapper对象。如果不需要再转换了,外面一定也没有强引用了,也就自动释放了。 |
OK,那#866 我关闭了,用你这个了 |
#867 用了这个PR的代码使用示例工程不崩,但是接入到项目中就崩,还是提示 |
如果按你的#866 修改没有问题的话,那应该是原本的BroadcastReceiver被直接注册到系统过。那它是怎么注册的呢? |
是的这也是让我费解的地方。 |
如果还有问题再打开吧。 |
系统控件 ViewFlipper 在 ShadowContext 没有重写 |
我也遇到了同样的问题 本来也想重写 registerReceiverAsUser方法,奈何已经变成了隐藏api,无法被重写。 |
我的修改方案:新增加了一个 public class ShadowContext extends SubDirContextThemeWrapper {
...
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
BroadcastReceiverWrapper wrapper = getReceiverWrapperFromMap(receiver);
if (wrapper != null) {
super.unregisterReceiver(wrapper);
} else {
super.unregisterReceiver(receiver);
}
}
private BroadcastReceiverWrapper getReceiverWrapperFromMap(BroadcastReceiver receiver) {
if (receiver == null) {
return null;
}
synchronized (mReceiverWrapperMap) {
WeakReference<BroadcastReceiverWrapper> weakReference
= mReceiverWrapperMap.get(receiver);
return weakReference == null ? null : weakReference.get();
}
}
...
} |
Shadow对于BroadcastReceiver所需的处理只涉及onReceive方法传回的参数。 由于插件的BroadcastReceiver是通过正常的Context对象直接注册到系统中的, 所以对于系统来说这些BroadcastReceiver和宿主的其他BroadcastReceiver 没有什么区别。系统回调onReceive方法时传回的Context和Intent也都是宿主的。 其中需要把Context换回ShadowContext,Intent中的ClassLoader换回插件的。 Tencent#865#issuecomment-1134246493指出:系统控件 ViewFlipper 在 onAttachedToWindow() 方法中使用 Contenxt.registerReceiverAsUser 方法进行广播注册;在 onDetachedFromWindow() 方法中使用 Context.unregisterReceiver 方法进行取消广播注册。 本地提交改为通过Transform修改插件中的onReceive方法,在BroadcastReceiver 内部进行参数转换。从而避免引入新的类型,同时也不依赖如何注册和反注册Receiver。 fix Tencent#865 close Tencent#1105
Shadow对于BroadcastReceiver所需的处理只涉及onReceive方法传回的参数。 由于插件的BroadcastReceiver是通过正常的Context对象直接注册到系统中的, 所以对于系统来说这些BroadcastReceiver和宿主的其他BroadcastReceiver 没有什么区别。系统回调onReceive方法时传回的Context和Intent也都是宿主的。 其中需要把Context换回ShadowContext,Intent中的ClassLoader换回插件的。 Tencent#865#issuecomment-1134246493指出:系统控件 ViewFlipper 在 onAttachedToWindow() 方法中使用 Contenxt.registerReceiverAsUser 方法进行广播注册;在 onDetachedFromWindow() 方法中使用 Context.unregisterReceiver 方法进行取消广播注册。 本地提交改为通过Transform修改插件中的onReceive方法,在BroadcastReceiver 内部进行参数转换。从而避免引入新的类型,同时也不依赖如何注册和反注册Receiver。 fix Tencent#865 close Tencent#1105
Shadow对于BroadcastReceiver所需的处理只涉及onReceive方法传回的参数。 由于插件的BroadcastReceiver是通过正常的Context对象直接注册到系统中的, 所以对于系统来说这些BroadcastReceiver和宿主的其他BroadcastReceiver 没有什么区别。系统回调onReceive方法时传回的Context和Intent也都是宿主的。 其中需要把Context换回ShadowContext,Intent中的ClassLoader换回插件的。 Tencent#865#issuecomment-1134246493指出:系统控件 ViewFlipper 在 onAttachedToWindow() 方法中使用 Contenxt.registerReceiverAsUser 方法进行广播注册;在 onDetachedFromWindow() 方法中使用 Context.unregisterReceiver 方法进行取消广播注册。 本地提交改为通过Transform修改插件中的onReceive方法,在BroadcastReceiver 内部进行参数转换。从而避免引入新的类型,同时也不依赖如何注册和反注册Receiver。 fix Tencent#865 close Tencent#1105
Shadow对于BroadcastReceiver所需的处理只涉及onReceive方法传回的参数。 由于插件的BroadcastReceiver是通过正常的Context对象直接注册到系统中的, 所以对于系统来说这些BroadcastReceiver和宿主的其他BroadcastReceiver 没有什么区别。系统回调onReceive方法时传回的Context和Intent也都是宿主的。 其中需要把Context换回ShadowContext,Intent中的ClassLoader换回插件的。 #865#issuecomment-1134246493指出:系统控件 ViewFlipper 在 onAttachedToWindow() 方法中使用 Contenxt.registerReceiverAsUser 方法进行广播注册;在 onDetachedFromWindow() 方法中使用 Context.unregisterReceiver 方法进行取消广播注册。 本地提交改为通过Transform修改插件中的onReceive方法,在BroadcastReceiver 内部进行参数转换。从而避免引入新的类型,同时也不依赖如何注册和反注册Receiver。 fix #865 close #1105
``fix(core.runtime): BroadcastReceiver与BroadcastReceiverWapper映射Map采用弱引用实现
这次的提交在反注册的时候应该是有问题的
起因是我这里报了一个异常Receiver not registered: com.tencent.shadow.core.runtime.BroadcastReceiverWrapper
然后看代码,反注册的时候未在mReceiverWrapperMap中的的还会往mReceiverWrapperMap中put一个,且反注册的时候没有remove掉相应的Receiver
The text was updated successfully, but these errors were encountered: