Logcat에서 안무가 메시지의 의미
는 최신 의 의최신버설습다니치를 했습니다.SDK (API 16)
그리고 최신 ADT를 받았습니다.저는 지금 이 메시지들을 로그캣에서 보고 있습니다. 제가 전에 본 적이 없는 것은 확실합니다.이것에 대해 아는 사람 있나요?
06-29 23:11:17.796: I/Coorographer(691):647 프레임을 건너뛰었습니다!응용 프로그램이 메인 스레드에서 너무 많은 작업을 수행하고 있을 수 있습니다.
검색해보니 http://developer.android.com/reference/android/view/Choreographer.html 이라는 링크가 있었습니다.API 16에 도입된 새로운 클래스입니다.
모든 처리가 완료된 상태에서 응용프로그램이 "너무 많은 작업"을 수행하고 있는지 확인하는 방법을 알아야 합니다.AsyncTask
s의
안무가는 앱이 직접 vSync에 연결하고 시간을 적절하게 조정하여 성능을 향상시킬 수 있도록 지원합니다.
Android View 애니메이션은 내부적으로 동일한 목적으로 Choorographer를 사용합니다. 즉, 애니메이션 시간을 적절하게 조정하고 성능을 향상시키기 위한 것입니다.
안무가는 모든 vSync 이벤트에 대해 알려주기 때문에 Choreographer.post * 아피스에 전달된 Runnables 중 하나가 한 프레임 내에 완료되지 않아 프레임을 건너뛸 수 있습니다.
제가 알기로는 안무가는 프레임 건너뛰기만 감지할 수 있습니다.왜 이런 일이 일어나는지 알 수 있는 방법이는 없습니다.
"응용 프로그램이 메인 스레드에서 너무 많은 작업을 수행하고 있습니다."라는 메시지는 오해의 소지가 있습니다.
파티에 늦었지만, 이것이 여기 있는 다른 대답들에 유용하게 추가되기를 바랍니다.
질문에 대답하기 /tl:dr;
모든 처리가 비동기 작업에서 수행되기 때문에 응용프로그램이 "너무 많은 작업"을 수행하고 있는지 확인할 수 있는 방법을 알아야 합니다.
다음은 모두 후보입니다.
- 스레드에서 가능 로드,, 하기)
Uri
의 차례ImageView
모두 메인 스레드의 IO 구성) - /깊은/깊은 렌더링
View
구조 - 의많 의 많은 하는 것.
View
구조 - 비싼.
onDraw
정의 사의 방법의View
의 - 애니메이션의 경우 값비싼 계산이 발생합니다.
- 스레드를 "background로 간주하기에는 너무 높은 우선순위로 실행")
AsyncTask
이고 "background"입니다.java.lang.Thread
아님) - 많은 쓰레기를 발생시켜 쓰레기 수집기가 청소하는 동안 주 실을 포함하여 "세상을 멈추게" 합니다.
실제로 특정 원인을 확인하려면 앱을 프로파일링해야 합니다.
더 자세한 정보
저는 코드를 보고 실험하면서 안무가를 이해하려고 노력해왔습니다.
안무가의 문서는 "애니메이션의 타이밍, 입력 및 그리기"로 시작하는데, 이것은 실제로 좋은 설명이지만, 나머지는 애니메이션을 지나치게 강조합니다.
안무가는 실제로 다음과 같은 순서로 실행되는 세 가지 유형의 콜백을 실행할 책임이 있습니다.
- 입력 처리 콜백(터치 이벤트와 같은 사용자 입력 처리)
- 프레임 간의 조정을 위한 애니메이션 콜백으로, 실행 중인 모든 애니메이션에 안정적인 프레임 시작 시간을 제공합니다.이러한 콜백을 두 번째로 실행하면 세 번째 유형의 콜백이 실행될 때까지 애니메이션 관련 계산(예: View의 위치 변경)이 이미 수행되었음을 의미합니다.
- 뷰 계층 구조를 그리기 위한 뷰 횡단 콜백.
그 목적은 무효화된 보기를 다시 그리는 속도(및 애니메이션 조정 속도)를 화면 vsync(일반적으로 60fps)와 일치시키는 것입니다.
건너뛴 프레임에 대한 경고는 나중에 생각한 것처럼 보입니다.세 단계를 통과하는 한 번의 패스가 예상 프레임 기간의 30배를 초과하는 경우 메시지가 기록되므로 로그 메시지에 표시될 수 있는 최소 수는 "30프레임 건너뛰기"입니다. 각 패스가 50% 이상 소요되면 30프레임을 건너뛸 수 있지만 경고는 표시되지 않습니다.
할 수 . 대의중부무의 하는 것View
계이나층View
복잡한 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.
다음 기간 동안 스택에서 확인할 수 있습니다.onDraw
애니메이션 제작 여부와 관계없이 안무가가 참여합니다.
예를 들어안무가를 짜증나게 하는 활동 $1. on Draw (Anoy)Android.view에서 안무가 활동.java:25).View.draw(View.java:13759)
꽤 많은 반복...
안드로이드 뷰에서.Android.view에서 ViewGroup.drawChild(ViewGroup.java:3169).Android.view에서 ViewGroup.dispatchDraw(ViewGroup.java:3039).안드로이드에서 View.draw(View.java:13762).위젯com.android에서 FrameLayout.draw(FrameLayout.java:467).내부의.보험 증권Android.view에서 PhoneWindow$DecorView.draw(PhoneWindow.java:2396).Android.view에서 View.getDisplayList(View.java:12710).Android.view에서 View.getDisplayList(View.java:12754)를 확인합니다.Android.view에서 HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1144).Android.view에서 ViewRootImppl.draw(ViewRootImppl.java:2273)를 확인합니다.루트 임플 보기.Android.view에서 Draw(ViewRootImppl.java:2145)를 수행합니다.루트 임플 보기.Android.view에서 Traversals(ViewRootImppl.java:1956)를 수행합니다.Android.view에서 ViewRootImppl.doTraversal(ViewRootImppl.java:1112)을 확인합니다.Android.view에서 ViewRootImppl$TraversalRunnable.run(ViewRootImppl.java:4472)을 확인합니다.Android.view에서 안무가 $CallbackRecord.run(안무가.java:725).Android.view의 안무가.doCallbacks(안무가.java:555)Android.view의 안무가.doFrame(안무가.java:525)Android.os에서 안무가 $FrameDisplayEventReceiver.run(안무가.java:711).Android.os에서 Handler.handleCallback(Handler.java:615).Android.os에서 Handler.dispatchMessage(Handler.java:92).Android.app의 Looper.loop(Looper.java:137).활동스레드.main(활동)스레드.java:4898)
마지막으로, 메인 스레드에서 수행할 수 있는 작업의 양을 줄이는 다른 스레드와의 경합이 있는 경우, 실제로 메인 스레드에서 작업을 수행하지 않더라도 프레임을 건너뛸 가능성이 크게 증가합니다.
이러한 상황에서 앱이 메인 스레드에서 너무 많은 작업을 수행하고 있다고 제안하는 것은 오해를 불러일으킬 수 있지만 Android는 작업자 스레드가 메인 스레드를 굶기지 않도록 낮은 우선순위로 실행되기를 정말 원합니다.작업자 스레드의 우선 순위가 낮은 경우 안무가 경고를 트리거하는 유일한 방법은 메인 스레드에서 너무 많은 작업을 수행하는 것입니다.
여러 상황에서 LogCat에 정보 메시지가 나타날 수 있습니다.
저의 경우 XML 레이아웃 파일에서 여러 보기를 프로그래밍 방식으로 부풀릴 때 발생했습니다.메시지 자체는 해롭지 않지만, 앱에서 사용할 수 있는 모든 RAM을 사용하여 엄청난 규모의 Force Close(강제 종료)가 발생할 수 있는 나중의 문제의 징후일 수 있습니다.저는 Log WARN/INFO/ERROR Free를 보고 싶어하는 개발자로 성장했습니다. ;)
이것이 제 경험입니다.
메시지를 받았습니다.
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 웹 서비스의 응답에서 온 데이터(페이징 기능 없음)로 채우는 방식으로 사용자 지정 "초복잡한 다중 섹션 목록"을 만들 때 이 보기는 행 역할을 합니다.모든 하위 섹션 헤더와 섹션 헤더를 올바른 순서로 선형 레이아웃(스크롤 뷰 내부의 수직 방향)에 추가합니다.목록 시뮬레이션 클릭 가능한 요소로 보기...하지만 음, 그건 다른 질문입니다.
책임감 있는 개발자로서 시스템 리소스로 앱을 정말 효율적으로 만들고 싶기 때문에 목록에 대한 최선의 방법은 목록 활동 또는 목록 조각을 로더와 함께 사용하고 목록 보기를 어댑터와 함께 채우는 것입니다. 이 방법이 실제로 더 효율적이며 항상 수행해야 합니다.당신의 목록이 그렇게 복잡하지 않다면.
솔루션:저는 REST/JSON 웹 서비스에서 "큰 응답 크기"를 방지하기 위해 페이징을 구현했으며 메인 스레드를 시원하게 유지하기 위해 비동기 작업에 "행", "섹션 헤더" 및 "하위 섹션 헤더" 보기를 추가한 코드를 래핑했습니다.
그래서... 제 경험이 이 정보 메시지로 머리를 깨부수는 다른 누군가에게 도움이 되길 바랍니다.
해피 해킹!
일반적으로 에뮬레이터를 사용하여 디버깅할 때 이 문제가 발생합니다. 에뮬레이터는 속도가 느린 것으로 알려져 있습니다.
저의 경우 진행 표시줄 결정에서 셜록 액션 표시줄을 보여줄 때 이러한 메시지가 나타납니다.제 라이브러리가 아니기 때문에 안무가 출력을 숨기기로 했습니다.
다음 필터 식을 사용하여 Logcat 보기에서 안무가 출력을 숨길 수 있습니다.
태그:^((?)안무가).*)$
저는 다른 곳에서 설명한 정규 표현을 사용했습니다: 단어가 포함되지 않은 줄과 일치하는 정규 표현?
언급URL : https://stackoverflow.com/questions/11266535/meaning-of-choreographer-messages-in-logcat
'source' 카테고리의 다른 글
Linux에서 Windows 컨테이너를 호스팅할 수 있습니까? (0) | 2023.08.19 |
---|---|
Angular에서 .subscribe는 무엇입니까? (0) | 2023.08.19 |
javascript Object.defineProperty를 사용하는 방법 (0) | 2023.08.19 |
Android:Enum을 번들에 넣는 방법? (0) | 2023.08.19 |
도커 파일 이름 지정 방법 (0) | 2023.08.19 |