ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

您是否在单独的线程上绘制图表?
感谢您的评论,我编辑了问题以使其更清楚。运行时的活动显示我正在运行一个没有设计布局的活动=>显示白屏。
@Areks 不,我没有使用单独的线程。
我认为您应该,根本不建议您在主线程上执行长时间操作,因为这会冻结整个应用程序,您可以在此处阅读如何使用线程:stackoverflow.com/questions/3391272/… 忽略“执行 HTTP 请求的代码”,只需在那里执行您可能需要很长时间的操作。
为什么不尝试搜索,您会找到有关编舞的信息。我建议您阅读此答案:stackoverflow.com/questions/11266535/…

J
Jorgesys

取自:Android UI : Fixing skipped frames

任何开始开发 android 应用程序的人都会在 logcat 上看到此消息“Choreographer(abc): Skipped xx frames!应用程序可能在其主线程上做了太多工作。”那么它实际上意味着什么,为什么要担心以及如何解决它。

这意味着您的代码需要很长时间才能处理,并且因此跳过了帧,这可能是因为您在应用程序或数据库访问的核心进行了一些繁重的处理或导致线程的任何其他事情停一会儿。

这里有一个更详细的解释:Choreographer 让应用程序将自己连接到 vsync,并适当地计时以提高性能。 Android 视图动画在内部使用 Choreographer 的目的相同:正确计时动画并可能提高性能。由于 Choreographer 被告知每个 vsync 事件,因此我可以判断 Choreographer.post* api 传递的其中一个 Runnables 是否没有在一帧的时间内完成,从而导致帧被跳过。据我了解,Choreographer 只能检测到跳帧。它无法说明为什么会发生这种情况。消息“应用程序可能在其主线程上做太多工作。”可能会产生误导。来源:Logcat 中 Choreographer 消息的含义 为什么你应该担心当这个消息在 android 模拟器上弹出并且跳过的帧数相当少(<100)那么你可以安全地押注模拟器很慢 - 这几乎发生一直以来。但是,如果跳过的帧数很大并且大约 300+,那么您的代码可能会出现一些严重的问题。与 ios 和 windows 设备不同,Android 设备具有大量硬件。 RAM 和 CPU 各不相同,如果您想在所有设备上获得合理的性能和用户体验,那么您需要修复这个问题。当跳过帧时,UI 很慢且滞后,这不是理想的用户体验。如何解决它 解决这个问题需要识别存在或可能发生长时间处理的节点。最好的方法是在与主 UI 线程分开的线程中进行所有处理,无论线程大小。因此,无论是从 SQLite 数据库访问数据,还是做一些核心数学运算,或者只是对数组进行排序——在不同的线程中执行现在这里有一个问题,您将创建一个新线程来执行这些操作,当您运行应用程序时,它会崩溃说“只有创建视图层次结构的原始线程才能触摸它的视图”。你需要知道这个事实,android 中的 UI 可以由主线程或 UI 线程更改。尝试这样做的任何其他线程都会失败并因此错误而崩溃。您需要做的是在 runOnUiThread 中创建一个新的 Runnable,并且在这个 runnable 中您应该执行所有涉及 UI 的操作。在这里找到一个例子。所以我们有 Thread 和 Runnable 来处理主线程之外的数据,还有什么? android 中有 AsyncTask 可以在 UI 线程上进行长时间的处理。当您的应用程序是数据驱动的或 Web api 驱动的或使用复杂的 UI(例如使用 Canvas 构建的那些)时,这是最有用的。 AsyncTask 的强大之处在于它允许在后台执行操作,一旦完成处理,您就可以简单地在 UI 上执行所需的操作,而不会造成任何滞后效果。这是可能的,因为 AsyncTask 是从 Activity 的 UI 线程派生而来的——您通过 AsyncTask 在 UI 上执行的所有操作都是与主 UI 线程不同的线程完成的,不会妨碍用户交互。因此,这是您制作流畅的 android 应用程序需要了解的内容,据我所知,每个初学者都会在他的控制台上收到此消息。


我只有一个应用程序,如果我点击一个按钮,按钮的背景图像会改变,并且按钮是不可点击的。我怎么做的工作太多了:(
@BenJaminSila 在 AsyncTask 中更改背景?真的吗?
@user25“假设您正在下载此图像”
“当此消息在 android 模拟器上弹出并且跳过的帧数相当少(<100)时,您可以安全地押注模拟器运行缓慢”这仍然适用于今天吗?模拟器变得非常快对吧?
AsyncTask 现已弃用!
W
Willi Mentzel

正如其他人在上面回答的那样,“跳过了 55 帧!”意味着您的应用程序中有一些繁重的处理。

就我而言,我的申请中没有繁重的过程。我仔细检查了所有内容并删除了那些我认为有点繁重的过程。

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

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


也为我工作。我有一个应用程序做的工作很少,但又慢又迟钝。我不断收到跳帧日志。一旦我从我的活动中删除了背景,一切都很好。谢谢!
很好的答案,我相信这正是我的问题。我尝试了一堆其他(相当复杂的)解决方案,但应用程序同样慢。我拿出了所有的网络服务,并试图优化我的代码。没有工作,然后我看到了这个。一旦我删除了我的背景图片(我拥有的最大图片),该应用程序的运行速度与您点击内容一样快,即使使用旧的“慢”代码也是如此。
@batsheva 不必为 1 KB。这取决于您的需求,假设您需要更清晰的图像,您可以使用更高的分辨率,但请确保您将资源分成不同的大小到不同的文件夹中。
我没有图像,所有图标的尺寸都很小,但您能否给我另一个解决方案还需要时间。如果你有
这个答案让我的夜晚......在尝试了近 5 个小时后拯救了我整个晚上......
C
Community

我也有同样的问题。我的情况是,我使用的是可绘制对象中的背景图像。该特定图像约为 130kB,并在我的 android 应用程序的初始屏幕和主页期间使用。

解决方案 - 我只是将该特定图像从 drawables 转移到 drawables-xxx 文件夹,并且能够释放后台占用的大量内存,并且跳过的帧不再跳过。

更新 使用“nodp”可绘制资源文件夹来存储背景可绘制文件。
Will a density qualified drawable folder or drawable-nodpi take precedence?


我将我的大背景图像从 drawable 移动到 mimap-xxxhdpi,它成功了!
这个解决方案可以解决问题。我使用文件夹 drawable-xxxhdpi 而不是 drawable,这大大减少了已用内存(减少了约 70%)。也很高兴知道,相同尺寸的屏幕在 DPI 大小上有所不同。它们之间的像素比为 ldpi = 1:0.75mdpi = 1:1hdpi = 1:1.5xhdpi = 1:2xxhdpi = 1:3xxxhdpi = 1:4。通过使用 drawable-xxxhdpi 文件夹,您可以将图像缩小到设备的屏幕尺寸,从而减少内存和 CPU 消耗。
将图像从 drawable 移动到 drawable-nodpi 会阻止应用程序获取 Out of Memory Error
天哪……谢谢!我在可绘制文件夹中有一张图片,这让我的应用程序慢得要命(尽管图片只有 100kb !!!)。生成 drawable-xxx 文件后(我使用了 Android Drawable Importer),我的应用程序非常快。非常感谢!
但是如何创建drawable-xxx文件夹?
u
user1643723

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

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

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


对于这种情况,您应该更喜欢 apply() 方法而不是 commit()。 apply() 方法不能阻塞 UI。你可以从这里看developer.android.com/training/data-storage/shared-preferences
p
phen0menon

我有同样的问题。 Android Emulator 在 Android 上完美运行 < 6.0。当我使用模拟器 Nexus 5 (Android 6.0) 时,该应用程序的运行速度非常慢,日志中有 I/Choreographer: Skipped frames

因此,我通过将清单文件 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>

2022 年 1 月更新。根据@M.Ed 的评论:如果您的目标 API >= 14,则硬件加速默认为 enabled


对于那些将来阅读本文的人来说,这是不必要的。如果您的目标 API 高于 14 级,则默认启用硬件加速。根据文档。 “如果您的 Target API 级别 >=14,则默认启用硬件加速,但也可以显式启用。”来源:developer.android.com/guide/topics/graphics/hardware-accel
M
MigDus

尝试使用以下策略来提高您的应用程序性能:

如果可能,请使用多线程编程。即使您的智能手机只有一个内核(如果处理器有两个或更多,线程可以在不同的内核中运行),性能优势也是巨大的。使您的应用程序逻辑与 UI 分离很有用。使用 Java 线程、AsyncTask 或 IntentService。检查这个。

阅读并遵循 Android 开发网站的 misc 性能提示。在这里检查。


您的第一个链接要求您“...拥有经过验证的帐户...”才能访问它。
s
saba

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


R
Radoslav

我有同样的问题。就我而言,我有 2 个嵌套的相对布局。 RelativeLayout 总是必须进行两次测量传递。如果嵌套RelativeLayouts,你会得到一个指数测量算法。


H
HarshitG

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


通过java代码减小图像大小或使用photoshop裁剪图像..也可以使用compressor.io压缩图像
H
Hossein Karami

这通常发生在您在主线程中执行大型进程时。跳过少于 200 个的帧是可以的。但是如果跳过的帧超过 200 个,它会减慢应用程序 UI 线程的速度。您可以做的是在一个称为工作线程的新线程中执行这些进程,然后,当您想要访问并使用 UI 线程执行某些操作(例如:使用视图、findView 等执行某些操作)时,您可以使用处理程序或runOnUiThread(我更喜欢这个)为了显示处理结果。这绝对解决了问题。在这种情况下,使用工作线程非常有用,甚至必须使用。

https://stacklearn.ir


R
Rob

我有同样的问题。当我在另一台计算机上运行代码时,它运行良好。然而,在我的身上,它显示“应用程序可能在其主线程上做了太多工作”。

我通过重新启动Android工作室解决了我的问题[文件->无效缓存/重新启动->单击“无效并重新启动”]。


我不知道为什么您的解决方案有效。总之谢谢。
F
FractalBob

就我而言,这是因为我不小心在方法上设置了断点。一旦我清除它,消息就消失了,性能提高了很多。


M
Mohsen Emami

正如我首先首选使用 SVG 图像而不是所有其他类型一样,如果不可能,请使用一些图像处理工具(例如 Adobe PhotoshopFotosizer)压缩您的所有 PNGJPG 资源。最简单的方法之一是像 this 这样的在线图像压缩工具,它帮助我将所有图像文件减少到其初始大小的近 50%。


J
John De la cruz

这实际上不是问题。当您长时间使用调试器时会发生这种情况。拆下制动点并再次检查。


n
naamadheya

我的应用程序有同样的问题。但它除了在上面显示卡片列表和文本之外没有做任何事情。没有在后台运行。但后来经过一些调查发现,卡片背景的图像集导致了这种情况,即使它很小(350kb)。然后我使用 http://romannurik.github.io/AndroidAssetStudio/index.html 将图像转换为 9patch 图像。
这对我有用。


S
Shubham Ranakoti

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


H
Hector Morris

在对这个问题进行了大量研发之后,我得到了解决方案,

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

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

结论:-查看您的代码是否有任何您正在使用的原始文件很大。


d
de_billa_

首先阅读警告。它说主线程上有更多负载。所以你要做的就是在一个线程中运行更多工作的函数。


A
AlexPes

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

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

A
Addell El-haddad

对我来说那是 RoundedBackgroundColorSpan !在 textview 中,我删除了它(烧我的大脑去寻找它,因为它不会出现在像 Pixel 4 Xl 或三星 note 10+ 等真正的智能手机中,也出现在模拟器中,但在芯片设备中,视图速度很慢)。


F
FxMax

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


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅