简体   繁体   English

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

[英]The application may be doing too much work on its main thread

I am new to Android SDK/API environment.我是 Android SDK/API 环境的新手。 It's the first I am trying to draw a plot/chart.这是我第一次尝试绘制绘图/图表。 I tried running different kinds of sample codes on the emulator using 3 different free libraries, nothing is showing on the layout screen.我尝试使用 3 个不同的免费库在模拟器上运行不同类型的示例代码,布局屏幕上没有显示任何内容。 The logcat is repeating the following message: 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. 

The problem didn't persist and the chart worked when I ran a sample code pertaining to an evaluation copy of a licensed library.当我运行与许可库的评估副本有关的示例代码时,问题并没有持续存在并且图表有效。

taken from : Android UI : Fixing skipped frames取自: Android UI:修复跳过的帧

Anyone who begins developing android application sees this message on logcat “Choreographer(abc): Skipped xx frames!任何开始开发 android 应用程序的人都会在 logcat 上看到这条消息“Choreographer(abc):跳过 xx 帧! The application may be doing too much work on its main thread.”应用程序可能在其主线程上做了太多工作。” So what does it actually means, why should you be concerned and how to solve it.那么它究竟意味着什么,你为什么要担心以及如何解决它。

What this means is that your code is taking long to process and frames are being skipped because of it, It maybe because of some heavy processing that you are doing at the heart of your application or DB access or any other thing which causes the thread to stop for a while.这意味着您的代码需要很长时间来处理并且帧因此被跳过,这可能是因为您在应用程序或数据库访问的核心进行了一些繁重的处理或任何其他导致线程停一会儿。

Here is a more detailed explanation:这里有更详细的解释:

Choreographer lets apps to connect themselves to the vsync, and properly time things to improve performance. Choreographer 让应用程序将自己连接到 vsync,并正确安排时间以提高性能。

Android view animations internally uses Choreographer for the same purpose: to properly time the animations and possibly improve performance. Android 视图动画在内部使用 Choreographer 用于相同目的:正确计时动画并可能提高性能。

Since Choreographer is told about every vsync events, I can tell if one of the Runnables passed along by the Choreographer.post* apis doesnt finish in one frame's time, causing frames to be skipped.由于 Choreographer 被告知每个 vsync 事件,我可以判断是否由 Choreographer.post* apis 传递的 Runnable 之一没有在一帧的时间内完成,从而导致跳过帧。

In my understanding Choreographer can only detect the frame skipping.在我的理解 Choreographer 只能检测跳帧。 It has no way of telling why this happens.它无法说明为什么会发生这种情况。

The message “The application may be doing too much work on its main thread.”消息“应用程序可能在其主线程上做了太多工作。” could be misleading.可能会产生误导。

source : Meaning of Choreographer messages in Logcat来源: Logcat 中 Choreographer 消息的含义

Why you should be concerned为什么你应该担心

When this message pops up on android emulator and the number of frames skipped are fairly small (<100) then you can take a safe bet of the emulator being slow – which happens almost all the times.当此消息在 android 模拟器上弹出并且跳过的帧数相当小(<100)时,您可以安全地打赌模拟器速度很慢——这几乎总是发生。 But if the number of frames skipped and large and in the order of 300+ then there can be some serious trouble with your code.但是,如果跳过的帧数很大,达到 300+ 的数量级,那么您的代码可能会出现一些严重的问题。 Android devices come in a vast array of hardware unlike ios and windows devices.与 ios 和 windows 设备不同,Android 设备有各种各样的硬件。 The RAM and CPU varies and if you want a reasonable performance and user experience on all the devices then you need to fix this thing. RAM 和 CPU 各不相同,如果您想在所有设备上获得合理的性能和用户体验,那么您需要解决这个问题。 When frames are skipped the UI is slow and laggy, which is not a desirable user experience.当跳过帧时,UI 缓慢且滞后,这不是理想的用户体验。

How to fix it如何修复

Fixing this requires identifying nodes where there is or possibly can happen long duration of processing.解决这个问题需要识别存在或可能发生长时间处理的节点。 The best way is to do all the processing no matter how small or big in a thread separate from main UI thread.最好的方法是在与主 UI 线程分开的线程中进行所有处理,无论大小。 So be it accessing data form SQLite Database or doing some hardcore maths or simply sorting an array – Do it in a different thread因此,无论是从 SQLite 数据库访问数据还是进行一些核心数学运算,或者只是对数组进行排序——在不同的线程中进行

Now there is a catch here, You will create a new Thread for doing these operations and when you run your application, it will crash saying “Only the original thread that created a view hierarchy can touch its views“.现在这里有一个问题,您将创建一个新线程来执行这些操作,当您运行应用程序时,它会崩溃并提示“只有创建视图层次结构的原始线程可以触摸其视图”。 You need to know this fact that UI in android can be changed by the main thread or the UI thread only.您需要知道这个事实,android 中的 UI 只能由主线程或 UI 线程更改。 Any other thread which attempts to do so, fails and crashes with this error.任何其他尝试这样做的线程都会失败并因此错误而崩溃。 What you need to do is create a new Runnable inside runOnUiThread and inside this runnable you should do all the operations involving the UI.你需要做的是在 runOnUiThread 中创建一个新的 Runnable 并且在这个 runnable 中你应该完成所有涉及 UI 的操作。 Find an example here . 在此处查找示例。

So we have Thread and Runnable for processing data out of main Thread, what else?所以我们有 Thread 和 Runnable 来处理主线程之外的数据,还有什么? There is AsyncTask in android which enables doing long time processes on the UI thread. android 中有 AsyncTask 可以在 UI 线程上进行长时间的处理。 This is the most useful when you applications are data driven or web api driven or use complex UI's like those build using Canvas.当您的应用程序是数据驱动的或 web api 驱动的或使用复杂的 UI 时,这是最有用的,比如使用 Canvas 构建的那些。 The power of AsyncTask is that is allows doing things in background and once you are done doing the processing, you can simply do the required actions on UI without causing any lagging effect. AsyncTask 的强大之处在于它允许在后台执行操作,一旦完成处理,您就可以简单地在 UI 上执行所需的操作,而不会造成任何滞后效果。 This is possible because the AsyncTask derives itself from Activity's UI thread – all the operations you do on UI via AsyncTask are done is a different thread from the main UI thread, No hindrance to user interaction.这是可能的,因为 AsyncTask 派生自 Activity 的 UI 线程——您通过 AsyncTask 在 UI 上执行的所有操作都是与主 UI 线程不同的线程完成的,不会妨碍用户交互。

So this is what you need to know for making smooth android applications and as far I know every beginner gets this message on his console.因此,这是制作流畅的 android 应用程序所需的知识,据我所知,每个初学者都会在其控制台上收到此消息。

As others answered above, "Skipped 55 frames!"正如其他人在上面回答的那样,“跳过了 55 帧!” means some heavy processing is in your application.意味着您的应用程序中有一些繁重的处理。

For my case, there is no heavy process in my application.就我而言,我的应用程序中没有繁重的过程。 I double and triple checked everything and removed those process I think was a bit heavy.我对所有内容进行了两次和三次检查,并删除了那些我认为有点繁重的过程。

I removed Fragments, Activities, Libraries until only the skeleton was left.我删除了 Fragments、Activity、Libraries,直到只剩下骨架。 But still the problem did not go away.但问题仍然没有消失。 I decided to check the resources and found some icons and background I use are pretty big as I forgot to check the size of those resources.我决定检查资源,发现我使用的一些图标和背景非常大,因为我忘记检查这些资源的大小。

So, my suggestion is if none of the above answers help, you may also check your resource files size.所以,我的建议是,如果以上答案都没有帮助,您也可以检查您的资源文件大小。

I too had the same problem.我也有同样的问题。
Mine was a case where i was using a background image which was in drawables.That particular image was of approx 130kB and was used during splash screen and home page in my android app.我的情况是我使用的是可绘制对象中的背景图像。该特定图像大约为 130kB,并在我的 android 应用程序的启动画面和主页期间使用。

Solution - I just shifted that particular image to drawables-xxx folder from drawables and was able free a lot of memory occupied in background and the skipping frames were no longer skipping.解决方案- 我只是将该特定图像从 drawables 转移到 drawables-xxx 文件夹中,并且能够释放在后台占用的大量内存,并且不再跳过跳帧。

Update Use 'nodp' drawable resource folder for storing background drawables files.更新使用“nodp”可绘制资源文件夹来存储背景可绘制文件。
Will a density qualified drawable folder or drawable-nodpi take precedence? 密度合格的 drawable 文件夹或 drawable-nodpi 会优先吗?

Another common cause of delays on UI thread is SharedPreferences access. UI 线程延迟的另一个常见原因是 SharedPreferences 访问。 When you call a PreferenceManager.getSharedPreferences and other similar methods for the first time, the associated .xml file is immediately loaded and parsed in the same thread .当您第一次调用PreferenceManager.getSharedPreferences和其他类似方法时,关联的 .xml 文件会立即在同一线程中加载和解析。

One of good ways to combat this issue is triggering first SharedPreference load from the background thread, started as early as possible (eg from onCreate of your Application class).解决这个问题的一个好方法是从后台线程触发第一个 SharedPreference 加载,尽可能早地启动(例如,从应用程序类的onCreate开始)。 This way the preference object may be already constructed by the time you'd want to use it.这样,在您想要使用它时,可能已经构建了首选项对象。

Unfortunately, sometimes reading a preference files is necessary during early phases of startup (eg in the initial Activity or even Application itself).不幸的是,有时在启动的早期阶段(例如在初始活动或什至应用程序本身)读取首选项文件是必要的。 In such cases it is still possible to avoid stalling UI by using MessageQueue.IdleHandler .在这种情况下,仍然可以通过使用MessageQueue.IdleHandler来避免停止 UI。 Do everything else you need to perform on the main thread, then install the IdleHandler to execute code once your Activity have been fully drawn.完成您需要在主线程上执行的所有其他操作,然后安装 IdleHandler 以在您的 Activity 完全绘制后执行代码。 In that Runnable you should be able to access SharedPreferences without delaying too many drawing operations and making Choreographer unhappy.在该 Runnable 中,您应该能够访问 SharedPreferences,而不会延迟太多绘图操作并使 Choreographer 不高兴。

Try to use the following strategies in order to improve your app performance:尝试使用以下策略来提高您的应用程序性能:

  • Use multi-threading programming if possible.如果可能,使用多线程编程。 The performance benefits are huge, even if your smart phone has one core (threads can run in different cores, if the processor has two or more).性能优势是巨大的,即使您的智能手机只有一个内核(线程可以在不同的内核中运行,如果处理器有两个或更多)。 It's useful to make your app logic separated from the UI.使您的应用程序逻辑与 UI 分离很有用。 Use Java threads, AsyncTask or IntentService.使用 Java 线程、AsyncTask 或 IntentService。 Check this . 检查这个
  • Read and follow the misc performance tips of Android development website.阅读并遵循 Android 开发网站的其他性能提示。 Check here . 检查这里

I had the same problem.我有同样的问题。 Android Emulator worked perfectly on Android < 6.0. Android 模拟器在 Android < 6.0 上完美运行。 When I used emulator Nexus 5 (Android 6.0), the app worked very slow with I/Choreographer: Skipped frames in the logs.当我使用模拟器 Nexus 5 (Android 6.0) 时,应用程序在I/Choreographer: Skipped frames日志中的I/Choreographer: Skipped frames运行非常慢。

So, I solved this problem by changing in Manifest file hardwareAccelerated option to true like this:因此,我通过将 Manifest file hardwareAccelerated选项更改为true来解决这个问题,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <application android:hardwareAccelerated="true">
        ...
    </application>
</manifest>

I am not an expert, but I got this debug message when I wanted to send data from my android application to a web server.我不是专家,但是当我想将数据从我的 android 应用程序发送到网络服务器时,我收到了这条调试消息。 Though I used AsyncTask class and did the data transfer in background, for getting the result data back from server I used get() method of the AsyncTask class which makes the UI synchronous which means that your UI will be waiting for too long.虽然我使用 AsyncTask 类并在后台进行数据传输,但为了从服务器取回结果数据,我使用了 AsyncTask 类的 get() 方法,这使 UI 同步,这意味着您的 UI 将等待太长时间。 So my advice is to make your app do every network oriented tasks on a separate thread.所以我的建议是让你的应用在一个单独的线程上完成每一个面向网络的任务。

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

I had the same problem.我有同样的问题。 In my case I had 2 nested Relative Layouts.就我而言,我有 2 个嵌套的相对布局。 RelativeLayout always has to do two measure passes. RelativeLayout 总是需要做两次测量传递。 If you nest RelativeLayouts, you get an exponential measurement algorithm.如果嵌套 RelativeLayouts,则会得到指数测量算法。

this usually happens when you are executing huge processes in main thread.这通常发生在您在主线程中执行大型进程时。 it's OK to skip frames less than 200. but if you have more than 200 skipped frames, it can slow down your application UI thread.跳过小于 200 的帧是可以的。但是如果跳过的帧超过 200,它会减慢应用程序 UI 线程的速度。 what you can do is to do these processes in a new thread called worker thread and after that, when you want to access and do something with UI thread(ex: do something with views, findView etc...) you can use handler or runOnUiThread (I like this more) in order to display the processing results.您可以做的是在一个称为工作线程的新线程中执行这些过程,之后,当您想访问并使用 UI 线程执行某些操作时(例如:使用视图、findView 等执行某些操作...),您可以使用处理程序或runOnUiThread (我更喜欢这个)以显示处理结果。 this absolutely solves the problem.这绝对解决了问题。 using worker threads are very useful or even must be used when it comes to this cases.使用工作线程非常有用,甚至在这种情况下必须使用。

I had the same problem.我有同样的问题。 When I ran the code on another computer, it worked fine.当我在另一台计算机上运行代码时,它运行良好。 On mine, however, it displayed "The application may be doing too much work on its main thread".然而,在我的上,它显示“应用程序可能在其主线程上做了太多工作”。

I solved my problem by restarting Android studio [File -> Invalidated caches / Restart -> click on "Invalidate and Restart"].我通过重新启动 Android Studio [文件 -> 无效缓存/重新启动 -> 单击“无效并重新启动”] 解决了我的问题。

In my case, it was because I had accidentally set a breakpoint on a method.就我而言,这是因为我不小心在方法上设置了断点。 Once I cleared it, the message went away and performance improved a lot.一旦我清除了它,消息就消失了,性能也有了很大的提高。

My app had same problem.我的应用程序有同样的问题。 But it was not doing other than displaying list of cards and text on it.但除了在上面显示卡片和文本列表之外,它并没有做其他事情。 Nothing running in background.没有什么在后台运行。 But then after some investigation found that the image set for card background was causing this, even though it was small(350kb).但是后来经过一些调查发现卡片背景的图像设置导致了这种情况,即使它很小(350kb)。 Then I converted the image to 9patch images using http://romannurik.github.io/AndroidAssetStudio/index.html .然后我使用http://romannurik.github.io/AndroidAssetStudio/index.html将图像转换为 9patch 图像。
This worked for me.这对我有用。

I got same issue while developing an app which uses a lot of drawable png files on grid layout.我在开发一个应用程序时遇到了同样的问题,该应用程序在网格布局上使用了大量可绘制的 png 文件。 I also tried to optimize my code as far as possible.. but it didn't work out for me.. Then i tried to reduce the size of those png.. and guess its working absolutely fine.. So my suggestion is to reduce size of drawable resources if any..我也尝试尽可能优化我的代码..但它对我没有用..然后我试图减少那些 png 的大小..并猜测它的工作绝对正常..所以我的建议是减少可绘制资源的大小(如果有)..

After doing much R&D on this issue I got the Solution,在对这个问题做了大量研发之后,我得到了解决方案,

In my case I am using Service that will run every 2 second and with the runonUIThread, I was wondering the problem was there but not at all.在我的情况下,我使用的服务将每 2 秒运行一次,并且使用 runonUIThread,我想知道问题是否存在,但根本没有。 The next issue that I found is that I am using large Image in may App and thats the problem.我发现的下一个问题是我在 may App 中使用了大图像,这就是问题所在。

I removed the Images and set new Images.我删除了图像并设置了新图像。

Conclusion :- Look into your code is there any raw file that you are using is of big size.结论:-查看您的代码是否有任何您使用的原始文件很大。

First read the warning.首先阅读警告。 It says more load on main thread.它说主线程上的负载更多。 So what you have to do is just run functions with more work in a thread.所以你要做的就是在一个线程中运行更多工作的函数。

As I did first preferably use SVG images instead of all other types, If not possible compress all of your PNG and JPG resources using some image processing tools such as Adobe Photoshop or Fotosizer .正如我最初所做的那样,最好使用SVG图像而不是所有其他类型,如果不可能,请使用一些图像处理工具(如Adobe PhotoshopFotosizer压缩所有PNGJPG资源。 one of the easiest ways is online image compressing tools like this which helped me to decrease all my image files to almost 50% of their initial size.最简单的方法之一是像这样的在线图像压缩工具,它帮助我将所有图像文件减小到其初始大小的近 50%。

Have not resolved yet but will do.尚未解决,但会解决。 For my tiny project with one composable function (button) and logic to check if "com.whatsapp" packages exists on device (emulator) i have the following in the same log while starting simulator :对于具有一个可组合功能(按钮)和逻辑以检查设备(模拟器)上是否存在“com.whatsapp”包的小型项目,我在启动模拟器时在同一日志中具有以下内容:

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

This is actually not a problem.这实际上不是问题。 This happens when you have the debugger for a long time.当您长时间使用调试器时会发生这种情况。 Remove the brake point and check again.拆下制动点并再次检查。

For me that was RoundedBackgroundColorSpan, in textview. I remove it so (burn my brain to find it because It doesn't appear in real smartphones like Pixel 4 Xl or Samsung note 10+ also in emulator but in chip device this slow a view).对我来说,那是 textview 中的 RoundedBackgroundColorSpan。我将其删除(燃烧我的大脑来找到它,因为它没有出现在像 Pixel 4 Xl 或 Samsung note 10+ 这样的真实智能手机中,也没有出现在模拟器中,但在芯片设备中,这个视图很慢) .

如果您在应用程序中使用 async/await 功能,这是正常的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 应用程序可能在其主线程上做太多工作 - Application may be doing too much work on its main thread 应用程序可能在其主线程消息上做过多的工作 - the application may be doing too much work on its main thread message 该应用程序可能在其主线程上做太多工作-Android - The application may be doing too much work on its main thread - Android Android-该应用程序可能在其主线程上做了大量工作 - Android - The application may be doing too much work on its main thread 片段:应用程序可能在其主线程上做太多工作 - Fragment: The application may be doing too much work on its main thread MapFragment-应用程序可能在其主线程上做过多的工作 - MapFragment - The application may be doing too much work on its main thread Android:该应用程序可能在其主线程上做了大量工作 - Android : The application may be doing too much work on its main thread 此应用程序可能在其主线程中做过多的工作 - This application may be doing too much work in its main thread 我的应用程序可能在其主线程上做过多的工作 - My application may be doing too much work on its main thread 该应用程序可能在其主线程上做过多的工作 - The application may be doing too much work on its main thread
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM