Shadow icon indicating copy to clipboard operation
Shadow copied to clipboard

插件调用到宿主AppcomatDialog崩溃

Open OldWilliam opened this issue 3 years ago • 5 comments

代码在这:demo

宿主和插件都设置了AppCompat主题,并且都能正常弹出AppcomatDialog,只有插件调用到宿主会崩溃。

09-09 12:08:36.032 5355 5355 E AndroidRuntime: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity. 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:852) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:815) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:703) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at androidx.appcompat.app.AppCompatDialog.setContentView(AppCompatDialog.java:95) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at androidx.appcompat.app.AlertController.installContent(AlertController.java:232) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at androidx.appcompat.app.AlertDialog.onCreate(AlertDialog.java:279) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at android.app.Dialog.dispatchOnCreate(Dialog.java:421) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at android.app.Dialog.show(Dialog.java:315) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at androidx.appcompat.app.AlertDialog$Builder.show(AlertDialog.java:1009) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at com.tencent.shadow.sample.host.lib.MPermissions.requestPermission(MPermissions.java:36) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at com.tencent.shadow.sample.plugin.app.lib.usecases.host_communication.PluginUseHostClassActivity$1.onClick(PluginUseHostClassActivity.java:77) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at android.view.View.performClick(View.java:7201) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at android.view.View.performClickInternal(View.java:7170) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at android.view.View.access$3500(View.java:806) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at android.view.View$PerformClick.run(View.java:27562) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:883) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:100) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at android.os.Looper.loop(Looper.java:214) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7682) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516) 09-09 12:08:36.032 5355 5355 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

OldWilliam avatar Sep 09 '22 04:09 OldWilliam

我看了一下代码,这个表现是很正常的。

你在宿主和插件中都打包了androidx.appcompat:appcompat:1.4.1。这个包中与androidx.appcompat.app.AlertDialog相关的不止有Java类,还有它的资源androidx.appcompat.R.styleable.AppCompatTheme等。

你没有像hostWhiteList = ["com.tencent.shadow.sample.host.lib"]一样,将androidx.appcompat添加到白名单中。因此你在插件和宿主中使用的androidx.appcompat.app.AlertDialog是两个不同的类。但也并不是你把这个包加到白名单中就行了。Shadow没有提供插件复用宿主资源的能力,因此插件和宿主中的androidx.appcompat.R类会分别生成不同的值。因此appcompat这种带有资源的第三方库确实不能在插件和宿主中简单的复用。需要更复杂的、额外的固定复用R值的构建流程。

由于你把MPermissions放到了本就在白名单中的com.tencent.shadow.sample.host.lib包,所以这个类插件和宿主访问的都是宿主中的类。它引用的androidx.appcompat.app.AlertDialog也是宿主中的类。因此当你把插件的context传给它时,它的AppCompatDelegateImpl.java:850行代码 if (!a.hasValue(R.styleable.AppCompatTheme_windowActionBar))中向这个插件context查询的R值是来自宿主的。向插件context查询宿主中的R值,这显然是会失败的。

从你的代码意图来看,你是想让插件通知宿主弹出一个Dialog。那么你的MPermissions对象应该提前持有宿主Activity作为Context。

shifujun avatar Sep 09 '22 07:09 shifujun

感谢回复~

image 这里可以看到在调用到宿主的时候,会把插件的context转换为宿主里面的Activity,也就是壳Activity。

这样也不行,是要持有其他Activity吗,还是说要宿主ApplicationContext。

OldWilliam avatar Sep 09 '22 08:09 OldWilliam

壳Activity用的是插件的资源,它没有宿主的资源。你既然想让宿主弹出dialog,就让用宿主那个前台activity作为context就是正确的。

shifujun avatar Sep 09 '22 08:09 shifujun

插件运行的时候,前台的Activity就是在宿主的占位Activity,PluginDefaultProxyActivity。你是说上一个Activity吗。

如果是用上一个的话,会导致弹到当前Activity下面,Dialog会不可见。

OldWilliam avatar Sep 09 '22 08:09 OldWilliam

这种是不是没有什么好的解法,只能改造宿主,禁用AppCompatDialog改为系统dialog。

OldWilliam avatar Sep 09 '22 09:09 OldWilliam