首页 文章

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

提问于
浏览
290

我是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 回答

  • 413

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

  • 54

    正如其他人在上面回答的那样,“跳过了55帧!”意味着您的申请中会有一些繁重的处理 .

    就我而言,我的申请中没有繁重的过程 . 我对所有内容进行了双重和三重检查,并删除了我认为有点沉重的过程 .

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

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

  • 5

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

    所以,我通过将Manifest文件 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>
    
  • 17

    在这个问题上做了大量的研发后,我得到了解决方案,

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

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

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

  • 185

    您可以使用Glide库来加载图像..它将在后台线程上加载图像..

  • 5

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

    我通过重新启动Android studio [File - > Invalidated caches / Restart - >点击“Invalidate and Restart”]解决了我的问题 .

  • -2

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

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

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

  • 7

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

  • 1

    取自: Android UI : Fixing skipped frames

    任何开始开发Android应用程序的人都会在logcat上看到这条消息“Choreographer(abc):Skipped xx frames!应用程序可能在其主线程上做了太多工作 . “那么它究竟意味着什么,为什么要关注它以及如何解决它 . 这意味着您的代码需要很长时间才能处理并且因为它而跳过框架,这可能是因为您在应用程序或数据库访问的核心进行了一些繁重的处理,或者导致该线程的任何其他因素停一会儿 . 下面是一个更详细的解释:编排器允许应用程序将自己连接到vsync,并适当地计时以提高性能 . Android视图动画在内部使用Choreographer用于相同目的:正确计时动画并可能提高性能 . 由于Choreographer被告知每个vsync事件,我可以判断一个Runnables传递的Choreographer.post * apis是否在一帧的时间内没有完成,导致要跳过的帧 . 在我的理解中,编舞者只能检测跳帧 . 它无法说明为什么会发生这种情况 . 消息“应用程序可能在其主要线程上做了太多工作 . ”可能会产生误导 . 来源: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驱动时,或者使用像使用Canvas构建的复杂UI一样,这是最有用的 . AsyncTask的功能是允许在后台执行操作,一旦完成处理,您可以在UI上执行所需的操作,而不会产生任何滞后效果 . 这是可能的,因为AsyncTask从Activity的UI线程派生自己 - 你通过AsyncTask在UI上完成的所有操作都是与主UI线程不同的线程,不妨碍用户交互 . 所以这是你需要知道的平滑的Android应用程序,并且据我所知,每个初学者都在他的控制台上获取此消息 .

  • 5

    尝试使用以下策略以提高应用性能:

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

    • 阅读并遵循Android开发网站的misc性能提示 . Check here .

  • -2

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

  • 14

    首先阅读警告 . 它表示主线程上的负载更多 . 所以你要做的就是在一个线程中运行更多功能的函数 .

  • 1

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

  • 0

    我也有同样的问题 .
    我的情况是我使用的背景图像是drawables . 这个特定的图像大约130kB,并在我的Android应用程序中的启动画面和主页使用 .

    Solution - 我刚刚从drawables将该特定图像移动到drawables-xxx文件夹,并且能够释放大量占用背景的内存并且不再跳过跳帧 .

    Update 使用'nodp' drawable资源文件夹存储背景drawables文件 .
    Will a density qualified drawable folder or drawable-nodpi take precedence?

  • 0

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

相关问题