前言:请注意我只是一个初学的Android开发者,所以我完全有可能错过一些明显或者做得非常愚蠢的事情。
我正在开发一款需要实时滚动线图的应用。新值到达约。每100毫秒,我想通过在100ms / 16ms~6动画帧上向左滚动图形来动画它们的到来。我需要在两个图表上显示来自三个不同来源的大约50个值,总共需要绘制300行。每个显示帧(16ms)重新绘制整个图形。
我确实认识到有更有效的方法可以实现上述目标。我可以存储先前绘制的位图,而不是在右边添加一个小切片,而不是每帧都重新绘制所有内容。我也可以用GLES中的硬核方式来做。
但我认为我们有硬件加速是有原因的,而且300条直线并不像世界上最复杂的问题那样简单。毕竟,如果硬件加速能够以60 FPS的速度进行动态照明,那么它能否以实时速度为我绘制几条线?
嗯,事实证明,即使是硬件加速画布也很难有效地绘制这么多行。当图表独立时,它确实(几乎没有)跟上:
...但随着布局的复杂性,事情变得越来越糟糕 - 越来越多的帧被“计划好几毫秒,导致jank”(正如systrace所说):
我认为我正在做所有基本的事情:绘图是在自定义视图中完成的onDraw
(因为SurfaceView
而TextureView
不提供硬件加速画布),线坐标在后台线程上计算,以便onDraw
不做任何额外的工作,也在后台线程上生成点,我加倍努力使屏幕的右侧部分无效。
您可以在my GitHub repo中找到所有血腥细节和APK。感兴趣的两个文件是GraphView.java和MainActivity.java;由于长度不在这里发布。布局非常简单:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="net.davidcie.graphtest.MainActivity">
<net.davidcie.graphtest.GraphView
android:id="@+id/graph1"
android:layout_width="match_parent"
android:layout_height="80dp"
android:focusable="false"/>
<net.davidcie.graphtest.GraphView
android:id="@+id/graph2"
android:layout_width="match_parent"
android:layout_height="80dp"
android:focusable="false"/>
</LinearLayout>
在回购中,您还会发现systraces用于回购中的简单布局,以及在实际应用中提取测试用例的更复杂的布局。
请记住前言免责声明,我很乐意听取您的经验: