长SVG资产文件错误:R不是一个有效的动词。故障发生在路径的第2个位置:字符串太大。

16

我目前在使用Android Studio时遇到了一些问题,因为我最近开始使用“向量资源”。我已经完全做好了在我的应用程序中正确显示它们的必要工作(在xml中使用app:srcCompat="",在build.gradle中使用android {defaultConfig {vectorDrawables.useSupportLibrary true}},并在setContentView()之前的onCreate()方法中使用AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);)。

我导入到Android Studio中的svg文件本身没有错误,在向导中的ImageView中也可以看到结果而没有任何问题。唯一的问题是当我运行我的应用程序并且到达绘制svg的时间时,有些svg仍然有效,而其他的则不行,所以我认为其中一些处理时间过长。 这是错误:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.retroverse.bataille_corse, PID: 18807
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.retroverse.bataille_corse/com.retroverse.bataille_corse.MenuPrincipal}: android.view.InflateException: Binary XML file line #127: Binary XML file line #127: Error inflating class ImageView
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2985)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3120)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1840)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:201)
        at android.app.ActivityThread.main(ActivityThread.java:6872)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
     Caused by: android.view.InflateException: Binary XML file line #127: Binary XML file line #127: Error inflating class ImageView
     Caused by: android.view.InflateException: Binary XML file line #127: Error inflating class ImageView
     Caused by: android.content.res.Resources$NotFoundException: Drawable com.retroverse.bataille_corse:drawable/card_49_en with resource ID #0x7f060099
     Caused by: android.content.res.Resources$NotFoundException: File res/drawable/card_49_en.xml from drawable resource ID #0x7f060099
        at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:854)
        at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:634)
        at android.content.res.MiuiResourcesImpl.loadDrawable(MiuiResourcesImpl.java:329)
        at android.content.res.Resources.getDrawableForDensity(Resources.java:902)
        at android.content.res.Resources.getDrawable(Resources.java:841)
        at android.content.Context.getDrawable(Context.java:644)
        at androidx.core.content.ContextCompat.getDrawable(ContextCompat.java:454)
        at androidx.appcompat.widget.ResourceManagerInternal.getDrawable(ResourceManagerInternal.java:144)
        at androidx.appcompat.widget.ResourceManagerInternal.getDrawable(ResourceManagerInternal.java:132)
        at androidx.appcompat.content.res.AppCompatResources.getDrawable(AppCompatResources.java:104)
        at androidx.appcompat.widget.AppCompatImageHelper.loadFromAttributes(AppCompatImageHelper.java:59)
        at androidx.appcompat.widget.AppCompatImageView.<init>(AppCompatImageView.java:78)
        at androidx.appcompat.widget.AppCompatImageView.<init>(AppCompatImageView.java:68)
        at androidx.appcompat.app.AppCompatViewInflater.createImageView(AppCompatViewInflater.java:187)
        at androidx.appcompat.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:107)
        at androidx.appcompat.app.AppCompatDelegateImpl.createView(AppCompatDelegateImpl.java:1407)
        at androidx.appcompat.app.AppCompatDelegateImpl.onCreateView(AppCompatDelegateImpl.java:1457)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:776)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:734)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:867)
        at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:828)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:519)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:427)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
        at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:555)
        at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:161)
        at com.retroverse.bataille_corse.MenuPrincipal.onCreate(MenuPrincipal.java:24)
        at android.app.Activity.performCreate(Activity.java:7232)
E/AndroidRuntime:     at android.app.Activity.performCreate(Activity.java:7221)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1272)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2965)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3120)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1840)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:201)
        at android.app.ActivityThread.main(ActivityThread.java:6872)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
     Caused by: java.lang.IllegalArgumentException: R is not a valid verb. Failure occurred at position 2 of path: STRING_TOO_LARGE
        at android.util.PathParser.nCreatePathDataFromString(Native Method)
        at android.util.PathParser.access$200(PathParser.java:24)
        at android.util.PathParser$PathData.<init>(PathParser.java:76)
        at android.graphics.drawable.VectorDrawable$VFullPath.updateStateFromTypedArray(VectorDrawable.java:2016)
        at android.graphics.drawable.VectorDrawable$VFullPath.inflate(VectorDrawable.java:1967)
        at android.graphics.drawable.VectorDrawable.inflateChildElements(VectorDrawable.java:819)
        at android.graphics.drawable.VectorDrawable.inflate(VectorDrawable.java:717)
        at android.graphics.drawable.DrawableInflater.inflateFromXmlForDensity(DrawableInflater.java:142)
        at android.graphics.drawable.Drawable.createFromXmlInnerForDensity(Drawable.java:1332)
        at android.graphics.drawable.Drawable.createFromXmlForDensity(Drawable.java:1291)
        at android.content.res.ResourcesImpl.createFromXmlForDensity(ResourcesImpl.java:1506)
        at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:838)
            ... 41 more
我认为最重要的一行是Caused by: java.lang.IllegalArgumentException: R is not a valid verb. Failure occurred at position 2 of path: STRING_TOO_LARGE。我们也知道这个svg文件太大了(大小为187千字节)。所以我认为我的SVG文件(即使通过“矢量资产”导入到Android Studio中)也太重了。 正如我们在这里所说的那样,当字符串“长度超过0x7FFF = 32767个字符”时,会出现STRING_TOO_LARGE问题。(在复制部分) 事实上,在我的应用程序中能工作的唯一SVG都比32 kb轻,这可能就是原因。 但我确实需要正确地显示此SVG(不要提供将其转换为PNG!),如果可能的话,而且不需要优化它的路径。 任何帮助都将不胜感激!

问题所在的行(#127)是<path>中的strokeColor属性,但没有错误。如果我通过删除几个<path>(直到它低于32 kb),使用相同的svg文件,我可以无问题地显示它。如前所述,文件本身没有任何错误(也没有警告),只有当您绘制太重的svg时才会出现问题(肯定)。我希望找到一个解决这个错误的方法,仍然使用相同的svg。 - TheBigBadBoy
恐怕我有点被难住了。32kb的限制似乎相当糟糕。也许你可以想办法将SVG分成多个文件? - r3mainer
在花费了一些时间并尝试了几种方法后,这是唯一有效的方法:我使用矢量资源功能多次导入相同的svg文件,然后将矢量分成部分(在问题行之前剪切每个部分)。 我将所有这些矢量片段放在一个图层列表中。这些矢量片段现在小于10kb,绘制图层列表时完美无误地工作,没有任何错误。 我会继续通知您,看看我从中得到多少kb的错误(总是通过拆分svg文件)。 唯一的问题是它需要大量的时间... - TheBigBadBoy
最后,我立即进行了一项小测试,只要svg部件不超过约30kb,就没有问题。错误指示xml(矢量图)中的某一行,但实际上这并不是矢量图显示的限制(基本上,我将所谓的错误留在第127行,并保留了更大的矢量图部分,所有这些都没有超过32kb)。由于<path>的存在,我无法在32kb处正确地切割堆栈,这就是为什么我说“大约”的原因。 - TheBigBadBoy
也许你可以把你的发现转化为一个答案。无论如何,我会给你点赞的。 - r3mainer
显示剩余2条评论
2个回答

20

我终于找到答案了……

实际上,32 kb以上的矢量资源并没有真正的问题,一切取决于代码中的内容。我应该比平时更加注意警告,但我并不总是会这样做。

我在我的svg文件中发现了一个超过40kb的路径数据(在一个字符串中)。据问题中的网站所述,一个字符串不能超过(大约)32k个字符,否则任何xml文件中使用的整个字符串都将被替换为“STRING_TOO_LARGE”。无论如何,只要在这里删除这一行,我就可以完美地绘制矢量图形了(虽然它仍然是250 kb,但现在不完整了)。

很惊讶的是,Android Studio仅显示一个警告(当字符串长度超过32k个字符时),以让我了解具有长路径的svg可能会显示缓慢,而不是警告我路径太长就会损坏(最好是在IDE中将此警告转换成错误,以避免不愉快的意外)。


4
哪一行?在“这一行”中。 - htafoya
1
我的意思是删除标签<path />,其中android:pathData为“STRING_TOO_LARGE”,但结果矢量不再完整。最好的方法是将路径分成几个不同的“子路径”。 - TheBigBadBoy

13

多亏了@TheBigBadBoy,我将长的SVG路径分成了几个部分。我打开了图像的XML文件,并通过M符号来划分路径(另请参见如何在svg中将一个路径拆分为两个路径)。

<path
    android:fillColor="#ffffff"
    android:fillType="evenOdd"
    android:pathData="M40.255,47.8897C40.1686, ... ,47.8897ZM38.7713,40.2642L38.8362, ..., 46.0978Z"
    />

图片描述

您可以看到每个段落都以M开头,以Z结尾。您可以在第一个路径中保留约20Kb并剪切其尾部。然后将其尾部粘贴到第二个路径中。重复此过程直至所有路径的大小均小于32 Kb。

因此,您将得到:

<path
    android:fillColor="#ffffff"
    android:fillType="evenOdd"
    android:pathData="M40.255,47.8897C40.1686, ... ,47.8897Z"
    />

<path
    android:fillColor="#ffffff"
    android:fillType="evenOdd"
    android:pathData="M38.7713,40.2642L38.8362, ..., 46.0978Z"
    />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接