一张图引发的App crash

前言

UE提供的图片资源,一般除了做下压缩外,都是直接使用的。不过有一次UE提供了一张1*1尺寸的小图片后,却引发了app一个UI crash。下面想分享下该问题的原因及解决方案。
问题描述

java.lang.llegalArgumentException: Dimensions must be positive! provided (0, 0)

系统要求的尺寸是正的,但提供系统的尺寸却是0,即尺寸是0导致了问题的出现。这需要结合堆栈信息进行分析、定位。

原因定位

堆栈信息如下。这里只展示了Android系统API的堆栈,业务代码调用的地方被省略了,不过这些信息已经足够定位原因。

java.lang.llegalArgumentException: Dimensions must be positive! provided (0, 0)
at android.graphics.ImageDecoder.setTargetSize(lmageDecoder.java:1033)
at android.graphics.lmageDecoder.computeDensity(lmageDecoder.java:1823)
at android.graphics.ImageDecoder.decodeDrawablelmpl(lmageDecoder. java:1670)
at android.graphics.ImageDecoder.decodeDrawable(lmageDecoder.java:1645)
at android.content.res.Resourceslmpl.decodelmageDrawable(Resourceslmpl.java:766)
at android.content.res.Resourceslmpl.loadDrawableForCookie(Resourceslmpl.java:839)
at android.content.res.Resourceslmpl.loadDrawable(Resourceslmpl.java:631)
at android.content.res.Resources.loadDrawable(Resources.java:897)
at android.content.res.TypedArray.getDrawableForDensity(TypedArray.java:955)
at android.content.res.TypedArray.getDrawable(TypedArray.java:930)
at android.widget.ImageView.(lmageView.java:189)
at android.widget.ImageView.(lmageView.java:172)
......

由堆栈信息的第2行可见,最终引发问题的是ImageDecoder类下的setTargetSize方法。这里打开Android的源码看看setTargetSize方法的具体实现,如下。

public void setTargetSize(@Px @IntRange(from = 1) int width,                              
                          @Px @IntRange(from = 1) int height) {        
       if (width <= 0 || height <= 0) {            
               throw new IllegalArgumentException("Dimensions must be positive! " + "provided (" + width + ", " + height + ")");        
        }        
        
        mDesiredWidth = width;        
        mDesiredHeight = height;
}

可见,当width=0或height=0,setTargetSize方法会抛出异常。那么为什么width、height会等于0呢?根据堆栈信息继续往下看。computeDensity方法的源码实现如下。

private int computeDensity(@NonNull Source src) {    
        if (this.requestedResize()) {        
              return Bitmap.DENSITY_NONE;    
        }    
        
        final int srcDensity = src.getDensity();    
        if (srcDensity == Bitmap.DENSITY_NONE) {        
              return srcDensity;    
        }    
         
         if (mIsNinePatch && mPostProcessor == null) {        
               return srcDensity;    
         }    
         
         Resources res = src.getResources();    
         if (res != null && res.getDisplayMetrics().noncompatDensityDpi == srcDensity) {        
               return srcDensity;    
         }    
         
         final int dstDensity = src.computeDstDensity();    
         if (srcDensity == dstDensity) {        
               return srcDensity;    
         }    
         
         if (srcDensity < dstDensity && sApiLevel >= Build.VERSION_CODES.P) {        
               return srcDensity;    
         }    
         
         float scale = (float) dstDensity / srcDensity;    
         int scaledWidth = (int) (mWidth * scale + 0.5f);    
         int scaledHeight = (int) (mHeight * scale + 0.5f);    
         this.setTargetSize(scaledWidth, scaledHeight);    
         return dstDensity;
}

setTargetSize的width、height就是通过computeDensity方法传入。mWidth、mHeight是图片的尺寸,两个都为1。即宽、高的计算公式都为(int)(1 * scale + 0.5f)。到这里会发现,导致宽、高为0的罪魁祸首是scale。scale的计算公式为(float)dstDensity/srcDensity。根据系统API对dstDensity、srcDensity的描述可知,dstDensity为屏幕像素密度,srcDensity为APP传入的密度参数、取决于放入了哪一个图片文件。

在这里插入图片描述

因为该图片放进了xxhdpi文件夹中,即srcDensity为480。dstDensity这个值就需要根据手机系统的具体情况来分析。假如一台手机的分辨率为1920 * 1080,4.5英寸。dstDensity的值就为(1920 * 1920 + 1080 * 1080)开根号、再除以4.5,约等于489.5。此时scale=489.5 / 480 = 1,计算得到的宽、高也会大于0,这种情况是不会抛出异常的。但假如是在宽度较大的平板,尺寸是13.5,那么得到的dstDensity约等于163。在这种情况下,根据宽、高的计算公式:(int)(1 * (163 / 480) + 0.5f) = 0。这时候系统就会抛出异常,导致APP crash。

解决方式

原因定位后,有两种解决方案:

  • 方案1:找UE换一张尺寸不低于3*3的图片。
  • 方案2:删除该1*1的图片。
    和UE沟通后,该图片下个版本不会再使用,删除不会产生影响,于是采用了方案2。问题解决。

欢迎关注公众号度熊君,一起分享交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Win7中解决AppCrash事件的方法如下: 1. 更新操作系统和驱动程序:在Windows Update中查找并安装最新的更新。 2. 卸载不必要的程序:卸载不需要的软件和驱动程序,以减少系统资源的使用。 3. 检查病毒和恶意软件:使用杀毒软件扫描系统,并删除发现的病毒和恶意软件。 4. 重新启动计算机:重新启动计算机并再次运行应用程序,看看是否已解决问题。 5. 运行系统文件检查:在命令提示符下运行"sfc /scannow"命令,以确保系统文件完整性。 如果以上方法都无法解决问题,建议还可以尝试恢复系统,或联系技术支持。 ### 回答2: Appcrash事件是发生在Windows操作系统上的一种常见问题。当一个程序在执行过程中突然崩溃并关闭时,系统会提示一个错误,告诉你是这个程序发生了一个Appcrash事件。这种事件通常是由许多不同的原因引起的,包括软件或硬件故障、错误的驱动程序或损坏的系统文件等。虽然Appcrash问题看起来很棘手,但是有很多方法可以解决这个问题。 1. 检查系统文件 首先,可以运行sfc /scannow命令来检查是否有受损或缺失的系统文件。打开命令提示符窗口,并输入" sfc /scannow "并按 Enter 键。这将扫描系统文件并自动修复任何损坏的文件。 2. 更新驱动程序 Appcrash问题可能是由于错误的驱动程序引起的。因此,检查并更新所有的驱动程序是一个很好的选择。前往制造商的网站,找到适合你系统的最新驱动程序,并安装它们。 3. 清理系统文件 定期清理系统文件可以减少系统出现问题的可能性。使用Windows自带的磁盘清理工具可以删除不需要的文件和文件夹,包括程序缓存和日志文件等。 4. 更改兼容性设置 有时,Appcrash问题可能是由于应用程序与操作系统不兼容而引起的。可以右键单击应用程序的EXE文件,选择“属性”,然后选择“兼容性”选项卡。在这里,可以更改应用程序的兼容性设置,以使其与操作系统兼容。 5. 不使用过于老旧的软件 在使用比较老旧的软件时,有可能会出现Appcrash事件。这是因为新的操作系统并不兼容一些老旧的软件,而且这些软件的代码可能会变得越来越不稳定。因此,尽量不使用过于老旧的软件。 总之,Appcrash问题看起来很令人困扰,但实际上可以通过按照上述方法来解决。只要留意并及时修改,就可以使系统保持稳定运行。 ### 回答3: Appcrash事件是指在Windows 7操作系统中运行某些应用程序时,应用程序发生异常而导致系统崩溃或崩溃。这种情况可能是由于各种因素引起的,包括应用程序的错误配置、损坏的文件或系统文件缺失。 下面是一些解决Appcrash事件的方法: 1.升级或更新应用程序:有时,应用程序的老版本会出现各种可能的问题和漏洞,从而导致系统崩溃。升级或更新应用程序可修复这些问题,增强应用程序的稳定性和性能。 2.检查系统文件:如果Appcrash事件的原因是系统文件损坏或缺失,则需要手动检查系统文件并修复。可以通过“开始”菜单中的“命令提示符”运行系统文件检查工具,以查找和修复受损的文件。 3.关闭所有后台程序:如果您的计算机中同时运行了多个应用程序和后台程序,这可能会导致应用程序崩溃。尝试关闭所有非必要的后台程序,仅打开您需要的应用程序,这可以降低系统负载并提高系统稳定性。 4.重新安装应用程序:如果应用程序经常发生Appcrash事件并且无法修复,可能需要重新安装该程序。删除原先的应用程序,重新下载安装程序,重新安装并使用最新版本的应用程序。 5.清空临时文件:临时文件可以占据大量系统资源,从而导致应用程序崩溃,清空临时文件可以释放系统资源并提高系统稳定性。在“开始”菜单中,输入“%temp%”,删除其中的所有文件。 总之,如果您遇到Appcrash事件,可以尝试上述解决方法。如果仍然无法解决问题,可以搜索相关解决办法或者请教专业技术人员。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值