应用程序可能在其主线程上做了太多工作

时间:2013-02-03 23:29:29

标签: android multithreading

我是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. 

当我运行与许可库的评估副本有关的示例代码时,问题没有持续存在并且图表工作正常。

18 个答案:

答案 0 :(得分:429)

取自: Android UI : Fixing skipped frames

  

任何开始开发Android应用程序的人都会看到此消息   logcat “编舞(abc):跳过xx帧!申请可能是   在主线程上做了太多工作。“那实际上是什么呢   意思是,你为什么要关心它以及如何解决它。

     

这意味着您的代码需要很长时间才能处理和构建   正因为它而被跳过,可能是因为有些沉重   处理您正在应用程序或数据库核心的处理   访问或任何其他导致线程停止一段时间的事情。   这是一个更详细的解释:

     
    

Choreographer允许应用程序将自己连接到vsync,和     适当的时间来提高绩效。

         

Android视图动画在内部使用Choreographer     目的:适当地定时动画并可能改进     性能

         

由于Choreographer被告知每个vsync事件,我可以判断是否     其中一个Runnables由Choreographer.post * apis传递     在一帧的时间内没有完成,导致跳过帧。

         

在我的理解中,编舞者只能检测跳帧。     它无法解释为什么会发生这种情况。

         

消息“应用程序可能在其主要方面做了太多工作     线程。“可能会误导。

         

来源:     的 Meaning of Choreographer messages in Logcat

  
     

为什么你应该关注

     

当这个消息在android上弹出时   仿真器和跳过的帧数相当小(<100)   你可以安全地下注模拟器很慢 - 这发生了   几乎所有的时间。但是如果帧数跳过而且很大   并且在300+的顺序那么可能会有一些严重的麻烦   你的代码。与ios不同,Android设备拥有大量硬件   和Windows设备。 RAM和CPU会有所不同,如果你想要的话   在您所有设备上的合理性能和用户体验   需要解决这个问题。当跳过帧时,UI很慢   滞后,这不是一个理想的用户体验。

     

如何修复

     

修复此问题需要识别存在或的节点   可能会发生长时间的处理。最好的方法是做   所有处理无论一个线程分开多大或多大   来自主UI线程。所以它是从SQLite数据库访问数据或   做一些硬核数学或简单地排序数组 - 做一个   不同的线程

     

现在有一个问题,你将创建一个新的线程   这些操作以及运行应用程序时,它将崩溃   说“只有创建视图层次结构的原始线程才可以   触及它的观点“。你需要知道android中的UI可以是这样的事实   仅由主线程或UI线程更改。任何其他线程   试图这样做,失败并与此错误崩溃。你是什​​么   需要做的是在runOnUiThread和inside里面创建一个新的Runnable   这个runnable你应该做所有涉及UI的操作。找   一个例子here

     

所以我们有Thread和Runnable来处理主线程的数据,   还有什么?在Android中有AsyncTask可以做很长时间   UI线程上的进程。这对你来说最有用   应用程序是数据驱动或web api驱动或使用复杂的UI   像那些使用Canvas构建的。 AsyncTask就是这样的力量   允许在后台做事,一旦你做完了   处理时,您可以简单地在UI上执行所需的操作   造成任何滞后效应。这是可能的,因为AsyncTask   派生自Activity的UI线程 - 你所做的所有操作   在UI上通过AsyncTask完成的是与主UI不同的线程   线程,不妨碍用户交互。

     

所以这就是你需要知道的制作流畅的android   应用程序,据我所知,每个初学者都会得到这个消息   控制台。

答案 1 :(得分:206)

正如其他人在上面回答的那样,&#34;跳过55帧!&#34;意味着你的申请中有一些繁重的处理。

对于我的情况,我的申请中没有繁重的过程。我对所有内容进行了双倍和三重检查,并删除了我认为有点沉重的过程。

我删除了碎片,活动,库,直到只剩下骨架。但问题仍然没有消失。我决定检查资源,发现我使用的一些图标和背景非常大,因为我忘了检查这些资源的大小。

所以,我的建议是,如果上述答案都没有帮助,您也可以检查资源文件的大小。

答案 2 :(得分:18)

UI线程延迟的另一个常见原因是SharedPreferences访问。当您第一次调用PreferenceManager.getSharedPreferences和其他类似方法时,相关的.xml文件会立即加载并在同一个线程中解析

解决此问题的一个好方法是从后台线程触发第一个SharedPreference加载,尽可能早地启动(例如从Application类的onCreate开始)。这样,首选对象可能已经在您想要使用它时构建。

不幸的是,有时在启动的早期阶段(例如在初始Activity或甚至应用程序本身中)读取首选项文件是必要的。在这种情况下,仍然可以使用MessageQueue.IdleHandler来避免停止UI。在主线程上执行您需要执行的所有其他操作,然后安装IdleHandler以在完全绘制Activity后执行代码。在该Runnable中,您应该能够访问SharedPreferences而不会延迟太多的绘图操作并使Choreographer不满意。

答案 3 :(得分:16)

尝试使用以下策略以提高应用效果:

  • 如果可能,请使用多线程编程。即使您的智能手机有一个核心(线程可以在不同的核心运行,如果处理器有两个或更多),性能优势也是巨大的。使您的应用程序逻辑与UI分离是很有用的。使用Java线程,AsyncTask或IntentService。 Check this
  • 阅读并遵循Android开发网站的misc性能提示。 Check here

答案 4 :(得分:7)

我不是专家,但是当我想将数据从我的Android应用程序发送到Web服务器时,我得到了这个调试消息。虽然我使用了AsyncTask类并在后台进行了数据传输,但是为了从服务器获取结果数据,我使用了AsyncTask类的get()方法,这使得UI同步,这意味着你的UI将等待太长时间。所以我的建议是让你的应用程序在一个单独的线程上完成每个面向网络的任务。

答案 5 :(得分:5)

我遇到了同样的问题。在我的情况下,我有2个嵌套的相对布局。 RelativeLayout总是要做两次测量。如果嵌套RelativeLayouts,则会得到指数测量算法。

答案 6 :(得分:4)

优化图像...不要使用大于100KB的图像...图像加载需要太多CPU并导致应用程序挂起。

答案 7 :(得分:1)

我遇到了同样的问题。当我在另一台计算机上运行代码时,它工作正常。然而,在我看来,它显示了#34;应用程序可能在其主线程上做了太多工作&#34;。

我通过重启Android工作室解决了我的问题[文件 - &gt;无效的缓存/重新启动 - &gt;单击&#34;无效并重新启动&#34;]。

答案 8 :(得分:1)

这通常在您在主线程中执行长进程时发生。可以跳过少于200个的帧。但是,如果跳过的帧超过200个,则会降低应用程序用户界面的速度。您可以做的是在称为工作线程的新线程中进行这些处理,然后在与主线程通信时显示结果。在大多数情况下,AsyncTask和RunOnUiThread可以解决问题...

答案 9 :(得分:0)

还没有解决,但会解决。对于我的带有一个可组合功能(按钮)和逻辑来检查设备(模拟器)上是否存在“com.whatsapp”包的小项目,我在启动模拟器时在同一日志中有以下内容:

I/Choreographer: Skipped 34 frames!  The application may be doing too much work on its main thread.

答案 10 :(得分:0)

正如我最初所做的那样,最好使用 SVG 图像而不是所有其他类型,如果不可能,请使用一些图像处理工具(例如 {{1})压缩所有 PNGJPG }} 或 Adobe Photoshop。最简单的方法之一是使用 this 等在线图像压缩工具,它帮助我将所有图像文件缩小到其初始大小的近 50%。

答案 11 :(得分:0)

如果您在应用程序中使用异步/等待功能,这是正常现象。

答案 12 :(得分:0)

在我的情况下,这是因为我不小心在方法上设置了一个断点。一旦清除,消息消失了,性能大大提高了。

答案 13 :(得分:0)

首先阅读警告。它表示主线程上有更多负载。因此,您要做的就是在线程中运行具有更多工作的功能。

答案 14 :(得分:0)

在这个问题上做了很多R&amp; D后,我得到了解决方案,

在我的情况下,我使用的服务将每2秒运行一次,并且使用runonUIThread,我想知道问题是否存在但根本没有。 我发现的下一个问题是我在may App中使用了大图像,这就是问题所在。

我删除了图像并设置了新图像。

结论: - 查看您的代码是否有任何原始文件,您使用的是大尺寸。

答案 15 :(得分:0)

我的应用有同样的问题。但它除了显示卡片和文本列表之外没有其他功能。什么都没有在后台运行。但经过一些调查后发现卡片背景的图像设置导致了这种情况,即使它很小(350kb)。然后我用图像将图像转换为9patch图像 Facebook Object
这对我有用。

答案 16 :(得分:-2)

我在开发一个在网格布局上使用大量可绘制png文件的应用程序时遇到了同样的问题。我也试图尽可能地优化我的代码..但它对我没有用..然后我试图减少那些png的大小..并猜测它的工作绝对正常..所以我的建议是减少可绘制资源的大小,如果有的话......

答案 17 :(得分:-3)

您可以使用Glide库加载图片..它会在后台线程上加载图片..