我不熟悉android sdk/api环境。这是我第一次尝试画一个图表。我尝试在模拟器上使用3个不同的免费库运行不同类型的示例代码,但布局屏幕上没有显示任何内容。logcat正在重复以下消息:
W/Trace(1378): Unexpected value from nativeGetEnabledTags: 0
I/Choreographer(1378): Skipped 55 frames! The application may be doing too much work on its main thread.
当我运行一个与许可库的评估副本相关的示例代码时,问题并没有持续存在,并且图表工作正常。
15条答案
按热度按时间ars1skjm1#
摘自:android用户界面:修复跳过的帧
任何开始开发android应用程序的人都会在logcat“choreographer()”上看到这条消息:跳过了xx帧!应用程序可能在它的主线程上做了太多的工作。”那么它实际上意味着什么,你为什么要关心它,以及如何解决它。
这意味着你的代码需要花很长时间来处理,帧也因此被跳过,这可能是因为你在应用程序的核心进行了一些繁重的处理,或者数据库访问,或者其他导致线程停止一段时间的事情。
以下是更详细的解释:
choreographer允许应用程序将自己连接到vsync,并适当地调整时间以提高性能。
android view动画在内部使用choreographer的目的是相同的:正确地计时动画,并可能提高性能。
由于choreographer被告知每个vsync事件,因此我可以判断choreographer.post*API传递的一个Runnable是否在一帧时间内完成,从而导致跳过帧。
据我所知,编舞只能检测到跳帧。它无法解释为什么会发生这种情况。
“应用程序可能在其主线程上做了太多工作”的消息可能会误导用户。
来源:logcat中编舞信息的含义
你为什么要担心
当android emulator上弹出此消息并且跳过的帧数非常小(<100)时,您可以放心地打赌emulator速度很慢,这几乎总是发生的。但是,如果跳过的帧数很大,大约为300多帧,那么代码可能会出现一些严重的问题。与ios和windows设备不同,android设备有大量的硬件。ram和cpu各不相同,如果您想要在所有设备上获得合理的性能和用户体验,那么您需要解决这个问题。跳过帧时,ui速度慢且滞后,这不是理想的用户体验。
如何修复它
解决这一问题需要识别存在或可能发生长时间处理的节点。最好的方法是在与主ui线程分离的线程中执行所有处理,不管它有多小或多大。所以,无论是访问sqlite数据库中的数据,还是做一些核心的数学运算,或者只是对数组进行排序,都可以在不同的线程中进行
现在这里有一个陷阱,您将创建一个执行这些操作的新线程,当您运行应用程序时,它将崩溃,并说“只有创建视图层次结构的原始线程才能接触其视图”。您需要知道,android中的ui只能由主线程或ui线程更改。任何其他尝试这样做的线程都会失败并因此错误而崩溃。您需要做的是在runonuithread中创建一个新的runnable,在这个runnable中,您应该执行涉及ui的所有操作。在这里找到一个例子。
所以我们有线程和可运行线程来处理主线程之外的数据,还有什么?android中有asynctask,可以在ui线程上执行长时间进程。当您的应用程序是数据驱动的或web api驱动的,或者使用复杂的ui(如使用画布构建的ui)时,这是最有用的。asynctask的强大之处在于它允许在后台进行操作,一旦完成了处理,就可以在ui上简单地执行所需的操作,而不会造成任何滞后效应。这是可能的,因为asynctask本身来自活动的ui线程——您通过asynctask在ui上执行的所有操作都是在与主ui线程不同的线程中完成的,不会妨碍用户交互。
这就是制作流畅的android应用程序所需要知道的,据我所知,每个初学者都会在自己的控制台上看到这条信息。
f0ofjuux2#
正如上面其他人回答的,“跳过了55帧!”意味着您的应用程序中存在一些繁重的处理过程。
就我而言,我的申请没有繁重的流程。我反复检查了所有的东西,删除了那些我认为有点重的过程。
我删除了片段、活动和库,直到只剩下 backbone 。但问题仍然没有消失。我决定查看这些资源,发现我使用的一些图标和背景非常大,因为我忘了检查这些资源的大小。
因此,我的建议是,如果上述答案都没有帮助,您还可以检查资源文件的大小。
dfty9e193#
我也有同样的问题。
在我的例子中,我使用的背景图像是drawables。该特定图像约为130kb,在我的android应用程序的启动屏幕和主页中使用。
解决方案-我刚刚将特定的图像从drawables转移到drawables 文件夹,可以释放大量占用在后台的内存,跳过的帧不再跳过。
更新用于存储后台可绘制文件的“nodp”可绘制资源文件夹。
密度限定的可绘制文件夹或可绘制节点优先吗?
kq4fsx7k4#
ui线程延迟的另一个常见原因是SharedReferences访问。当你打电话给
PreferenceManager.getSharedPreferences
和其他类似的方法,关联的.xml文件第一次在同一个线程中被立即加载和解析。解决此问题的一个好方法是从后台线程触发第一个SharedReference加载,尽早启动(例如从
onCreate
您的应用程序类的)。这样,在您想要使用首选项对象时,它可能已经被构造好了。不幸的是,有时在启动的早期阶段(例如,在初始活动中,甚至在应用程序本身中),读取首选项文件是必要的。在这种情况下,仍然可以通过使用
MessageQueue.IdleHandler
. 完成在主线程上执行的所有其他操作,然后在活动完全绘制完成后安装idlehandler以执行代码。在该runnable中,您应该能够访问SharedReference,而不会延迟太多绘图操作,也不会让choreographer不高兴。mjqavswn5#
尝试使用以下策略来提高应用程序性能:
如果可能,使用多线程编程。即使您的智能手机只有一个内核,性能优势也是巨大的(如果处理器有两个或更多内核,线程可以在不同的内核中运行)。将应用程序逻辑与ui分离是很有用的。使用java线程、asynctask或intentservice。看看这个。
阅读并遵循android开发网站的其他性能提示。在这里检查。
7uzetpgm6#
我也有同样的问题。android emulator在android<6.0上运行良好。当我使用emulator nexus 5(安卓6.0)时,该应用程序的运行速度非常慢
I/Choreographer: Skipped frames
在日志中。所以,我通过更改清单文件解决了这个问题
hardwareAccelerated
选择true
这样地:w41d8nur7#
我不是Maven,但当我想将数据从android应用程序发送到web服务器时,我收到了这个调试消息。虽然我使用了asynctask类并在后台进行了数据传输,但为了从服务器返回结果数据,我使用了asynctask类的get()方法,这使ui同步,这意味着您的ui将等待太长时间。所以我的建议是让你的应用程序在一个单独的线程上完成所有面向网络的任务。
s8vozzvw8#
优化你的图像。。。不要使用大于100kb的图像。。。图像加载占用太多cpu,导致应用程序挂起。
mrzz3bfm9#
我也有同样的问题。在我的例子中,我有两个嵌套的相对布局。relativelayout总是要做两次测量。如果嵌套relativelayouts,则得到一个指数度量算法。
jmp7cifd10#
这通常发生在主线程中执行大型进程时。跳过少于200帧是可以的。但如果跳过的帧超过200帧,则会降低应用程序ui线程的速度。您可以做的是在一个名为worker thread的新线程中执行这些进程,然后,当您想要访问ui线程并使用ui线程执行某些操作时(例如:使用视图、findview等执行某些操作),您可以使用handler或runonuithread(我更喜欢这个)来显示处理结果。这绝对解决了问题。在这种情况下,使用辅助线程非常有用,甚至必须使用。
b4wnujal11#
我也有同样的问题。当我在另一台计算机上运行代码时,它运行得很好。然而,在我的屏幕上,它显示“应用程序可能在其主线程上做了太多的工作”。
我通过重新启动android studio[文件->无效缓存/重新启动->单击“无效并重新启动”]解决了我的问题。
bnl4lu3b12#
在我的例子中,这是因为我不小心在一个方法上设置了一个断点。一旦我清除了它,消息就消失了,性能也提高了很多。
ahy6op9u13#
我的应用程序也有同样的问题。但它除了在上面显示卡片和文字的列表外,并没有别的功能。后台没有运行任何内容。但经过一些调查后发现,卡背景设置的图像导致了这种情况,即使它很小(350kb)。然后我使用http://romannurik.github.io/androidassetstudio/index.html.
这对我有用。
lh80um4z14#
我在开发一个应用程序时遇到了同样的问题,该应用程序在网格布局上使用了大量可绘制的png文件。我还试图尽可能优化我的代码。。但这对我不起作用。。然后我试着缩小那些png的大小。。我猜它工作得非常好。。因此,我的建议是减少可提取资源的规模(如果有的话)。。
von4xj4u15#
在对这个问题进行了大量的研发之后,我找到了解决方案,
在我的情况下,我使用的服务将永远运行