当前位置: 首页 > 知识库问答 >
问题:

Logcat中编舞信息的含义[重复]

谈桐
2023-03-14

我安装了最新版本的SDK(API 16)并获得了最新的ADT。我现在在logcat中看到了这些消息,我很确定,我以前没有见过。有人对此有想法吗?

06-29 23:11:17.796:我/编舞(691):跳过647帧!应用程序可能在其主线程上做了太多工作。

我进行了搜索,找到了以下链接:http://developer.android.com/reference/android/view/Choreographer.html.这是API 16中引入的一个新类。

我需要知道如何确定我的应用程序可能在做什么“太多的工作”,因为我的所有处理都是在AsyncTask中完成的。

共有3个答案

东典
2023-03-14

这是一条信息消息,在许多情况下可能会出现在您的LogCat中。

在我的例子中,它发生在我以编程方式从XML布局文件中扩展多个视图时。该消息本身无害,但可能是以后出现问题的迹象,该问题将使用你的应用程序允许使用的所有RAM,并导致超级邪恶势力接近发生。我已经成长为那种喜欢看到自己的日志警告/信息/无错误的开发人员

所以,这是我自己的经历:

我得到消息:

10-09 01:25:08.373: I/Choreographer(11134): Skipped XXX frames!  The application may be doing too much work on its main thread.

... 当我创建自己的自定义“超级复杂多节列表”时,通过从XML中膨胀视图并填充其字段(图像、文本等…)对于来自REST/JSON web服务响应的数据(没有分页功能),此视图将充当行、小节头和节头,方法是将所有这些按正确的顺序添加到线性布局中(在ScrollView中具有垂直方向)。所有这些都是为了模拟具有可单击元素的listView。。。但这是另一个问题。

作为一名负责任的开发人员,您希望让应用程序真正有效地利用系统资源,因此列表的最佳实践(当您的列表不那么复杂时)是使用带有加载程序的ListActivity或ListFragment,并用适配器填充ListView,这应该更有效,事实上是这样,您应该一直这样做,再次。。。如果你的清单不是那么复杂。

解决方案:我在我的REST/JSON web服务上实现了分页,以防止出现“大响应大小”,并且我包装了代码,在AsyncTask上添加了“行”、“节头”和“子节头”视图,以保持主线程冷却。

所以我希望我的经验能帮助其他人打开他们的脑袋,告诉他们这些信息。

快乐的黑客!

邢宏浚
2023-03-14

我迟到了,但希望这是对这里其他答案的有用补充...

我需要知道如何确定我的应用程序可能在做什么“太多的工作”,因为我的所有处理都是在Async任务中完成的。

以下是所有候选人:

  • IO或在主线程上进行昂贵的处理(加载绘图、膨胀布局和在ImageView上设置Uri都构成了主线程上的IO)
  • 渲染大型/复杂/深层<代码>视图<代码>层次结构
  • 使视图的大部分无效
  • 自定义视图中昂贵的onDraw方法
  • 动画中的昂贵计算
  • 以太高的优先级运行“worker”线程而不被视为“background”(默认情况下,异步任务是“background”,而java.lang.Thread不是)
  • 生成大量垃圾,导致垃圾收集器在清理时“停止世界”(包括主线程)

要实际确定具体原因,您需要分析您的应用程序。

我一直试图通过实验和查看代码来理解编舞。

Choreographer的文档以“协调动画、输入和绘图的计时”打开这实际上是一个很好的描述,但其余部分继续过度强调动画。

Choreographer实际上负责执行3种类型的回调,它们按以下顺序运行:

  1. 输入处理回调(处理用户输入,例如触摸事件)
  2. 用于在帧之间调整的动画回调,为正在运行的任何/所有动画提供稳定的帧开始时间。第二次运行这些回调意味着在调用第三种类型的回调时已经进行了任何与动画相关的计算(例如更改View的位置)...
  3. 用于绘制视图层次结构的视图遍历回调。

其目的是使无效视图的重新绘制(以及动画的过渡)速度与屏幕vsync相匹配,通常为60fps。

关于跳过帧的警告看起来像是事后才想到的:如果一次通过3个步骤需要超过预期帧持续时间的30倍,则会记录消息,因此您可以期望在日志消息中看到的最小数量是“跳过30帧”;如果每次通过的时间比应该的时间长50%,您仍然会跳过30帧(淘气!)但您不会收到警告。

从涉及的3个步骤中可以清楚地看出,触发警告的不仅仅是动画:用复杂的onDraw方法使大型视图层次结构或视图的重要部分无效可能就足够了。

例如,这将重复触发警告:

public class AnnoyTheChoreographerActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.simple_linear_layout);

        ViewGroup root = (ViewGroup) findViewById(R.id.root);

        root.addView(new TextView(this){
            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                long sleep = (long)(Math.random() * 1000L);
                setText("" + sleep);
                try {
                    Thread.sleep(sleep);
                } catch (Exception exc) {}
            }
        });
    }
}

... 这会产生如下日志记录:

11-06 09:35:15.865  13721-13721/example I/Choreographer﹕ Skipped 42 frames!  The application may be doing too much work on its main thread.
11-06 09:35:17.395  13721-13721/example I/Choreographer﹕ Skipped 59 frames!  The application may be doing too much work on its main thread.
11-06 09:35:18.030  13721-13721/example I/Choreographer﹕ Skipped 37 frames!  The application may be doing too much work on its main thread.

在绘制过程中,您可以从堆栈中看到,无论您是否正在制作动画,编舞都会参与其中:

例如。AnnoyTheChoreograph活动$1.on抽奖(AnnoyTheChoreograph erActivity.java:25)android.view.View.draw(View.java:13759)

... 有点重复。。。

在android上。看法视图组。android上的drawChild(ViewGroup.java:3169)。看法视图组。android上的dispatchDraw(ViewGroup.java:3039)。看法看法在android上绘制(View.java:13762)。小装置。框架布局。在com上绘制(FrameLayout.java:467)。Android内部的政策实施。PhoneWindow$DecorView。在android上绘制(PhoneWindow.java:2396)。看法看法android上的getDisplayList(View.java:12710)。看法看法android上的getDisplayList(View.java:12754)。看法硬件渲染器$GlRenderer。在android上绘制(HardwareRenderer.java:1144)。看法ViewRootImpl。在android上绘制(ViewRootImpl.java:2273)。看法ViewRootImpl。在android上执行Draw(ViewRootImpl.java:2145)。看法ViewRootImpl。在android上执行Traversals(ViewRootImpl.java:1956)。看法ViewRootImpl。android上的doTraversal(ViewRootImpl.java:1112)。看法ViewRootImpl$TraversalRunnable。在android上运行(ViewRootImpl.java:4472)。看法Choreographer$CallbackRecord。在android上运行(Choreographer.java:725)。看法编舞android上的doCallbacks(Choreographer.java:555)。看法编舞android上的doFrame(Choreographer.java:525)。看法Choreographer$FrameDisplayEventReceiver。在android上运行(Choreographer.java:711)。操作系统。处理程序。android上的handleCallback(Handler.java:615)。操作系统。处理程序。android上的dispatchMessage(Handler.java:92)。操作系统。活套。android上的loop(Looper.java:137)。应用程序。ActivityThread。main(ActivityThread.java:4898)

最后,如果来自其他线程的争用减少了主线程可以完成的工作量,即使您实际上并没有在主线程上完成工作,跳过帧的机会也会显着增加。

在这种情况下,暗示应用程序在主线程上做得太多可能会被认为是误导,但Android确实希望工作线程以低优先级运行,以防止它们耗尽主线程。如果工作线程的优先级较低,那么触发Choreographer警告的唯一方法实际上是在主线程上执行太多操作。

姚善
2023-03-14

Choreographer允许应用程序将自己连接到vsync,并适当地调整时间以提高性能。

Android view动画在内部使用Choreographer的目的是相同的:正确地计时动画,并可能提高性能。

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

据我所知,编舞只能检测到跳帧。它无法解释为什么会发生这种情况。

消息“应用程序可能在其主线程上做了太多工作。”可能会产生误导。

 类似资料:
  • 问题内容: 我现在不知道该LogCat条目的含义。有人能帮我吗? 问题答案: 其中至少有一个空对象,您不能拥有。 您可以通读源代码,并在此处看到这种情况:

  • 所以我得到了我想理解的代码,但我不知道这个操作符的含义: 如果你们能告诉我就太棒了谢谢

  • 我是Java的初学者,简单的东西对我来说是新的。除我的水平外,谷歌不想搜索这样的关键词,比如“- 我在这里找到的。所以我认为这个代码是正确的。 请帮助我理解这个表达是什么意思?

  • 技术规格 电池:3 x AAA 1.5V 碱性电池 最大称重能力:180 千克(397.8 磅) 体重显示分辨率:0.1 千克 / 0.2 磅 工作温度:0°C 至 45°C (32°F 至 113°F) 更换电池 Polar Balance 体重秤使用三个 AAA 1.5V 碱性电池。请使用已提供的电池。在您需要更换电池时,请勿使用充电电池或将新旧电池混合使用。 打开电池盖,取出旧电池。 将新电

  • 问题内容: 我正在JavaFx中创建一个应用程序,如果要打开任何子阶段,则应在其中进行操作,然后应在父阶段的中心打开它。我正在尝试使用它来执行此操作,但是它将子级分配到屏幕的中心,而不是父级的中心。如何将子阶段分配给父阶段的中心? 问题答案: 您可以使用父级的X / Y / width / height属性来执行此操作。除了使用,您可以执行以下操作: