【问题标题】:Android Canvas Path.OP Operation unexpected behaviour and randomly "freeze" with no outputAndroid Canvas Path.OP 操作意外行为并随机“冻结”且无输出
【发布时间】:2017-02-26 15:00:45
【问题描述】:

我正在改进我的应用程序以避免过度绘制并赢得更多帧/秒。

  1. 我需要首先构建一个自定义形状,我正在尝试通过创建不同的路径并通过 Path.Op.Union 将它们连接在一起。

  2. 然后,我通过 canvas.clipPath(shape, Region.Op.INTERSECT); 与该路径相交。在它上面我想画一个位图

  3. 目标是使位图具有在每个绘制周期中更改的最终路径/形状的形状。它基本上是一个带有自定义变形的圆圈,但其中嵌入了一个图像。

    DeformationCircleAnimator[] animation_vectors = new DeformationCircleAnimator[AnimationConfig.MAX_DEFORMATIONS_PER_CIRCLE];
    
    [...]
    
    Path shape =  createShapePath(); //1. Building the custom shape
    canvas.clipPath(shape, Region.Op.INTERSECT); //2. Adding shape to canvas to mold the bitmap into it
    canvas.drawBitmap(image, x1, y1, null); //3. positioning image in canvas and drawing it
    
    private Path createShapePath() {
        Path shape_path = new Path();
        shape_path.addCircle(circle.ball.centerX(), circle.ball.centerY(), circle.radius()*AnimationConfig.THUMBNAIL_SIZE_RATIO, Path.Direction.CW);
    
        for(int i=0; i!=animation_vectors.length; i++) {
            PointF[] points=animation_vectors[i].getThumbnailPoints();
            Path path = createDeformationPath(points);
            Log.d("DeformationController", "    After a while randomly blocks in this next step ");
            shape_path.op(path, Path.Op.UNION);
         }
    
        return shape_path;
    }
    
    private Path createDeformationPath(PointF[] points) {
        Path path = new Path();
    
        for(int i=0; i!=points.length; i++) {
            Log.d("DeformationController", "    Points("+i+"): " + points[i].toString());
        }
    
        path.moveTo(points[0].x, points[0].y);
        path.cubicTo(points[1].x, points[1].y, points[2].x, points[2].y, points[3].x, points[3].y);
        path.close();
    
        return path;
    }
    

我有一个动画正在运行,这意味着我的自定义视图在 20 毫秒到 20 毫秒之间失效,并且在我的视图的绘制方法中,我调用了一个运行此代码的方法。

我有两个问题。

  1. 第一个问题 过了一会儿,应用程序冻结在“shape_path.op(path, Path.Op.UNION);”行在我调用方法 createShapePath 之后。它不会崩溃,但它会一直呆在那里,直到 android os 询问我是否要等待任务或终止应用程序。这是一种奇怪的行为,因为有时会在 1、2、[..] 甚至 5 秒后发生。

  1. 第二个问题 - Path.Op.UNION 出现意外行为

我期待它基本上只构建一个形状,它是一个带有变形的圆形,但奇怪的是,它并没有让我成为路径的联合,似乎有时它会在碰撞点上切割它。

预期行为

发生了什么 - 意外行为:

(请注意,这些图像代表不同的时刻)

注释:

  1. 我将这 2 个问题发布到同一个帖子中,因为它们可能是相互关联的!
  2. 如果我绘制完整路径(而不是位图),结果与我构建完整路径时的问题含义完全相同。
  3. 我知道我可以构建位图并使用“paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));”然后绘制此位图以获得相同的结果,但这会变慢,这会使我的帧速率低于 15。(我需要每秒更多帧)

非常感谢您的帮助!

**********更新***************

我正在添加一些调试。以下几点是我在三次运算中使用的一些要点。事实上,它们是随机生成的:

[After running for some seconds, meaning that this is the part that the app decided to freeze - in this run]
10-17 15:18:30.200 27904-27904/com.test.app D/DeformationController:    button-1> CreateShapeCicle  : 5 | 889
10-17 15:18:30.201 27904-27904/com.test.app D/DeformationController:     Points(0): PointF(306.50906, 250.12515)
10-17 15:18:30.201 27904-27904/com.test.app D/DeformationController:     Points(1): PointF(192.68051, 262.03217)
10-17 15:18:30.201 27904-27904/com.test.app D/DeformationController:     Points(2): PointF(171.2101, 419.32123)
10-17 15:18:30.201 27904-27904/com.test.app D/DeformationController:     Points(3): PointF(276.74606, 461.8999)
10-17 15:18:30.201 27904-27904/com.test.app D/DeformationController:     After a while randomly blocks in this next step 
10-17 15:18:30.201 27904-27904/com.test.app D/DeformationController:     Unioning Done 
10-17 15:18:30.201 27904-27904/com.test.app D/DeformationController:     Points(0): PointF(230.44182, 425.0678)
10-17 15:18:30.201 27904-27904/com.test.app D/DeformationController:     Points(1): PointF(287.66864, 506.88214)
10-17 15:18:30.202 27904-27904/com.test.app D/DeformationController:     Points(2): PointF(442.31085, 447.52573)
10-17 15:18:30.202 27904-27904/com.test.app D/DeformationController:     Points(3): PointF(430.09357, 348.4287)
10-17 15:18:30.202 27904-27904/com.test.app D/DeformationController:     After a while randomly blocks in this next step 
10-17 15:18:30.203 27904-27904/com.test.app D/DeformationController:     Unioning Done 
10-17 15:18:30.203 27904-27904/com.test.app D/DeformationController:     Points(0): PointF(320.0, 470.7)
10-17 15:18:30.203 27904-27904/com.test.app D/DeformationController:     Points(1): PointF(434.83334, 472.7612)
10-17 15:18:30.203 27904-27904/com.test.app D/DeformationController:     Points(2): PointF(476.29462, 320.0204)
10-17 15:18:30.203 27904-27904/com.test.app D/DeformationController:     Points(3): PointF(375.35, 264.13098)
10-17 15:18:30.203 27904-27904/com.test.app D/DeformationController:     After a while randomly blocks in this next step 
10-17 15:18:30.204 27904-27904/com.test.app D/DeformationController:     Unioning Done 
10-17 15:18:30.204 27904-27904/com.test.app D/DeformationController:     Points(0): PointF(400.96085, 284.50278)
10-17 15:18:30.204 27904-27904/com.test.app D/DeformationController:     Points(1): PointF(323.55612, 198.45067)
10-17 15:18:30.204 27904-27904/com.test.app D/DeformationController:     Points(2): PointF(183.68585, 271.02948)
10-17 15:18:30.204 27904-27904/com.test.app D/DeformationController:     Points(3): PointF(212.13724, 384.90207)
10-17 15:18:30.204 27904-27904/com.test.app D/DeformationController:     After a while randomly blocks in this next step 
10-17 15:18:30.206 27904-27904/com.test.app D/DeformationController:     Unioning Done 
10-17 15:18:30.206 27904-27904/com.test.app D/DeformationController:     Points(0): PointF(222.2577, 308.0295)
10-17 15:18:30.206 27904-27904/com.test.app D/DeformationController:     Points(1): PointF(165.74612, 409.8604)
10-17 15:18:30.206 27904-27904/com.test.app D/DeformationController:     Points(2): PointF(280.00156, 518.0191)
10-17 15:18:30.206 27904-27904/com.test.app D/DeformationController:     Points(3): PointF(378.66205, 453.8789)
10-17 15:18:30.206 27904-27904/com.test.app D/DeformationController:     After a while randomly blocks in this next step 
10-17 15:18:30.208 27904-27904/com.test.app D/DeformationController:     Unioning Done 
10-17 15:18:30.211 27904-27904/com.test.app D/DeformationController:    button-2> CreateShapeCicle  : 5 | 890
10-17 15:18:30.211 27904-27904/com.test.app D/DeformationController:     Points(0): PointF(733.8789, 418.66205)
10-17 15:18:30.211 27904-27904/com.test.app D/DeformationController:     Points(1): PointF(796.7874, 321.89615)
10-17 15:18:30.211 27904-27904/com.test.app D/DeformationController:     Points(2): PointF(689.6939, 205.83849)
10-17 15:18:30.211 27904-27904/com.test.app D/DeformationController:     Points(3): PointF(588.0295, 262.2577)
10-17 15:18:30.211 27904-27904/com.test.app D/DeformationController:     After a while randomly blocks in this next step 
10-17 15:18:30.212 27904-27904/com.test.app D/DeformationController:     Unioning Done 
10-17 15:18:30.212 27904-27904/com.test.app D/DeformationController:     Points(0): PointF(573.3791, 271.59106)
10-17 15:18:30.212 27904-27904/com.test.app D/DeformationController:     Points(1): PointF(489.8216, 332.2361)
10-17 15:18:30.212 27904-27904/com.test.app D/DeformationController:     Points(2): PointF(551.4591, 484.26596)
10-17 15:18:30.212 27904-27904/com.test.app D/DeformationController:     Points(3): PointF(653.4909, 469.87485)
10-17 15:18:30.212 27904-27904/com.test.app D/DeformationController:     After a while randomly blocks in this next step 
10-17 15:18:30.213 27904-27904/com.test.app D/DeformationController:     Unioning Done 
10-17 15:18:30.213 27904-27904/com.test.app D/DeformationController:     Points(0): PointF(584.65, 455.86902)
10-17 15:18:30.213 27904-27904/com.test.app D/DeformationController:     Points(1): PointF(683.1479, 515.1188)
10-17 15:18:30.213 27904-27904/com.test.app D/DeformationController:     Points(2): PointF(794.6875, 402.43094)
10-17 15:18:30.213 27904-27904/com.test.app D/DeformationController:     Points(3): PointF(735.869, 304.65)
10-17 15:18:30.213 27904-27904/com.test.app D/DeformationController:     After a while randomly blocks in this next step 
10-17 15:18:30.214 27904-27904/com.test.app D/DeformationController:     Unioning Done 
10-17 15:18:30.214 27904-27904/com.test.app D/DeformationController:     Points(0): PointF(532.1372, 384.90207)
10-17 15:18:30.214 27904-27904/com.test.app D/DeformationController:     Points(1): PointF(555.6682, 495.87653)
10-17 15:18:30.214 27904-27904/com.test.app D/DeformationController:     Points(2): PointF(714.53656, 501.81717)
10-17 15:18:30.214 27904-27904/com.test.app D/DeformationController:     Points(3): PointF(745.8629, 392.36554)
10-17 15:18:30.214 27904-27904/com.test.app D/DeformationController:     After a while randomly blocks in this next step 
FREEZED

***** 已针对问题 2 更新 - 意外行为 *******

我添加了两个不同时刻的屏幕截图,但现在只加入了 2 条路径:圆形和一个立方路径。如果你看图片,你可以很容易地弄清楚什么是圆,什么是变形。正如您可能看到的那样,这种行为真的很奇怪,因为它似乎是 XOR 而不是 Union(我也尝试使用 addPath)。

注意:android的版本是kitkat: 4.4.2

【问题讨论】:

  • 你能用Path#addPath看看有什么不同吗?
  • addPath 解决了第 1 个问题,这意味着它停止冻结但第二个问题仍然存在,行为继续出现意外。我想避免透支。我会继续做一些测试。谢谢
  • 我不是 100% 确定您的问题 #2 是什么,但您是否尝试过 setFillType
  • 我更新了问题 n 2 的问题更加清晰。我还在这里录制了有关问题的视频:drive.google.com/open?id=0Bx62BNfVLJZDckRtZWVLcFpVTWc
  • 好的,我现在明白了:三次路径永远不能插入到一个完美的圆:而不是三次路径尝试弧

标签: android image animation canvas path


【解决方案1】:

可能会损害您的性能的一件事是您在绘制时不断分配 Path 对象并计算它们的值。也许您可以改为创建一个可能的 Path 对象数组,并根据动画开始后经过的毫秒数循环遍历它们。查看所有路径还可以帮助您准确指出您对奇数对象做错了什么(我的第一个猜测是cubicTo()正在做您不期望的事情,但是如果没有看到实际输入,很难说)。

【讨论】:

  • 我会尝试预先创建一个路径缓冲区并重用它。我在三次运算中使用的示例点上添加了一些调试。但是,这些值是随机生成的,这意味着它们在每个周期中完全相同的可能性很小。无论哪种方式,问题都不在于生成的点,因为它在我使用 Bitmap 和 PorterDuffXfermode 来实现效果的效率较低的应用程序中工作。感谢您的帮助!
  • 您是否尝试关闭硬件加速?我见过它的行为与预期不符的情况。
  • 我尝试了您的第一个猜测,方法是缓存 Path 对象并重用它,我还尝试关闭硬件加速,但问题仍然存在。
  • 您是否在其他设备/更高版本的操作系统上尝试过?
  • 所以,如果我在不同的设备上尝试更高的操作系统,行为会好得多,但我仍然注意到一些不良行为。今晚我会发布结果。 @pskink 写道,三次路径永远不能插入一个完美的圆(我也尝试过不完美的圆)所以这可能就是问题所在。我会做一些测试。
猜你喜欢
  • 1970-01-01
  • 2020-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多