응용 프로그램이 기본 스레드에서 너무 많은 작업을 수행하고있을 수 있습니다


379

Android SDK / API 환경이 처음입니다. 줄거리 / 차트를 그리는 것은 처음입니다. 3 개의 다른 무료 라이브러리를 사용하여 다른 종류의 샘플 코드 에뮬레이터를 실행하려고했지만 레이아웃 화면에 아무것도 표시되지 않습니다. logcat이 다음 메시지를 반복합니다.

 W / Trace (1378) : nativeGetEnabledTags에서 예기치 않은 값 : 0
 I / Choreographer (1378) : 55 프레임을 건너 !! 응용 프로그램이 기본 스레드에서 너무 많은 작업을 수행하고있을 수 있습니다.

라이센스 라이브러리의 평가판과 관련된 샘플 코드를 실행했을 때 문제가 지속되지 않고 차트가 작동했습니다.


2
별도의 스레드에서 차트를 그리십니까?
Areks

귀하의 의견에 감사드립니다. 더 명확하게하기 위해 질문을 편집했습니다. 실행 중 활동은 레이아웃 => 흰색 화면을 표시하는 디자인이없는 활동을 실행 중임을 나타냅니다.
user2038135

1
@Areks 아니요, 별도의 스레드를 사용하지 않습니다.
user2038135

1
: 나는 당신이, 즉 전체 응용 프로그램을 정지하기 때문에, 여기 스레드를 사용하는 방법을 읽을 수 주 스레드에서 오래 작업을 수행하는 데 전혀 사용하지 않는 것이 좋습니다한다고 생각 stackoverflow.com/questions/3391272/... 할 수있는 "코드를 무시 HTTP 요청 "으로 이동하여 잠재적으로 긴 작업을 수행하십시오.
Areks

1
검색을 시도하지 않는 이유는 안무가에 관한 정보입니다. 이 답변을 읽는 것이 좋습니다 : stackoverflow.com/questions/11266535/…
Gabriel Esteban

답변:


479

:에서 촬영 안드로이드 UI : 고정 프레임을 생략

안드로이드 애플리케이션 개발을 시작한 사람은 logcat “Choreographer (abc) : Skipped xx frames!” 에서이 메시지를 보게 됩니다! 응용 프로그램이 기본 스레드에서 너무 많은 작업을 수행하고있을 수 있습니다.” 따라서 실제로 무엇을 의미하는지, 왜 걱정해야하며 어떻게 해결해야합니까?

이것이 의미하는 것은 코드를 처리하는 데 시간이 오래 걸리고 프레임으로 인해 프레임을 건너 뛴다는 것입니다. 아마도 응용 프로그램이나 DB 액세스의 핵심 또는 스레드를 유발하는 다른 작업에서 수행하는 무거운 처리로 인해 잠시 멈춰라.

자세한 설명은 다음과 같습니다.

Choreographer를 사용하면 앱이 vsync에 연결되고 성능을 향상시킬 수있는 적절한 시간을 지정할 수 있습니다.

Android 뷰 애니메이션은 내부적으로 Choreographer를 사용하여 애니메이션의 시간을 적절하게 조정하고 성능을 향상시킵니다.

Choreographer는 모든 vsync 이벤트에 대해 알려주므로 Choreographer.post * api가 전달한 Runnable 중 하나가 한 프레임 시간 내에 완료되지 않아 프레임을 건너 뛰는 지 여부를 알 수 있습니다.

내 이해에서 Choreographer는 프레임 건너 뛰기 만 감지 할 수 있습니다. 왜 이런 일이 발생했는지 말할 방법이 없습니다.

"응용 프로그램이 기본 스레드에서 너무 많은 작업을 수행하고있을 수 있습니다."메시지 오해의 소지가 있습니다.

source : Logcat에서 안무가 메시지의 의미

왜 걱정해야합니까

이 메시지가 Android 에뮬레이터에서 팝업되고 건너 뛴 프레임 수가 상당히 적을 경우 (<100) 에뮬레이터가 느리게 안전하게 내기 할 수 있습니다. 거의 항상 발생합니다. 그러나 프레임 수가 건너 뛰고 300 + 이상이면 코드에 심각한 문제가 발생할 수 있습니다. Android 기기는 iOS 및 Windows 기기와 달리 다양한 하드웨어로 제공됩니다. RAM과 CPU는 다양하며 모든 장치에서 적절한 성능과 사용자 경험을 원하면이 문제를 해결해야합니다. 프레임을 건너 뛰면 UI가 느리고 느려져 바람직한 사용자 경험이 아닙니다.

고치는 방법

이를 해결하려면 처리 시간이 오래 걸리거나 발생할 수있는 노드를 식별해야합니다. 가장 좋은 방법은 기본 UI 스레드와 별 개인 스레드에서 크기가 작거나 크더라도 모든 처리를 수행하는 것입니다. 따라서 SQLite Database에서 데이터에 액세스하거나 하드 코어 수학을 수행하거나 단순히 배열을 정렬해야합니다. – 다른 스레드에서 수행

이제 여기에 캐치가 있습니다. 이러한 작업을 수행하기 위해 새 스레드를 작성하고 애플리케이션을 실행할 때 "보기 계층 구조를 작성한 원래 스레드 만 해당보기를 만질 수 있습니다"라는 오류가 발생합니다. 안드로이드의 UI는 메인 스레드 또는 UI 스레드에 의해서만 변경 될 수 있다는 사실을 알아야합니다. 이를 시도하는 다른 스레드는 실패하고이 오류와 충돌합니다. runOnUiThread 내부에 새로운 Runnable을 작성하고이 Runnable 내부에서 UI와 관련된 모든 조작을 수행해야합니다. 여기 에서 예를 찾으 십시오 .

메인 스레드에서 데이터를 처리하기 위해 Thread와 Runnable이 있습니다. 안드로이드에는 AsyncTask가있어 UI 스레드에서 장시간 프로세스를 수행 할 수 있습니다. 이것은 응용 프로그램이 데이터 구동 또는 웹 API 구동이거나 Canvas를 사용한 빌드와 같은 복잡한 UI를 사용할 때 가장 유용합니다. AsyncTask의 힘은 백그라운드에서 작업을 수행 할 수 있다는 것입니다. 처리를 마치면 지연 효과를 발생시키지 않고 UI에서 필요한 작업을 간단히 수행 할 수 있습니다. AsyncTask는 Activity의 UI 스레드에서 파생되기 때문에 가능합니다. AsyncTask를 통해 UI에서 수행하는 모든 작업은 기본 UI 스레드와 다른 스레드이므로 사용자 상호 작용에 방해가되지 않습니다.

그래서 이것은 부드러운 안드로이드 응용 프로그램을 만들기 위해 알아야 할 사항이며, 모든 초보자가 자신의 콘솔 에서이 메시지를 얻는다는 것을 알고 있습니다.


41
버튼을 클릭하면 버튼의 배경 이미지가 변경되고 버튼을 클릭 할 수없는 앱이 있습니다. 내가 너무 많은 일을 어떻게합니까 :(
Remian8985

1
@ Remian8985-버튼의 배경 이미지 변경 (이 이미지를 다운로드한다고 가정)은 AsyncTask에서 수행해야합니다. 즉, 백그라운드 다운로드 작업을 수행하고 결과를 UI 스레드 (이미지를 다시 제공)에 게시해야합니다. Android 참조 링크
BenJaminSila

11
@BenJaminSila가 AsyncTask에서 배경을 바꾸고 있습니까? 정말?
user25

11
@ user25 "이 이미지를 다운로드한다고 가정"
forresthopkinsa

"Android 에뮬레이터에서이 메시지가 표시되고 건너 뛴 프레임 수가 상당히 적을 경우 (<100) 에뮬레이터가 느리게 안전하게 내기를 걸 수 있습니다"오늘날에도 적용됩니까? 에뮬레이터가 꽤 빨라지고 있습니까?
Robin Dijkhof

243

다른 사람들이 위에서 대답했듯이 "55 프레임을 S습니다!" 응용 프로그램에 약간의 처리가 있음을 의미합니다.

필자의 경우에는 응용 프로그램에 많은 프로세스가 없습니다. 나는 두 배와 세 배로 모든 것을 확인하고 조금 무거웠다 고 생각하는 프로세스를 제거했습니다.

골격 만 남을 때까지 조각, 활동, 라이브러리를 제거했습니다. 그러나 여전히 문제는 사라지지 않았습니다. 나는 자원을 확인하기로 결정했고 내가 사용하는 일부 아이콘과 배경이 그 자원의 크기를 확인하는 것을 잊어 버린 꽤 큰 것을 발견했습니다.

따라서 위의 답변 중 어느 것도 도움이되지 않으면 리소스 파일 크기를 확인할 수도 있습니다.


1
나를 위해 일했습니다. 나는 거의 일을하지 않지만 느리고 게으른 응용 프로그램을 가지고있었습니다. 프레임 로그를 건너 뛰었습니다. 내 활동에서 배경을 제거하면 모든 것이 잘되었습니다. 감사!
akrabi

좋은 대답은 이것이 정확히 내 문제라고 생각합니다. 나는 다른 많은 (빠른 관련) 솔루션을 시도했지만 응용 프로그램은 느 렸습니다. 나는 모든 웹 서비스를 꺼내고 코드를 뼈까지 최적화하려고했습니다. 작동하지 않았다, 나는 이것을 보았다. 배경 이미지 (가장 큰 이미지)를 제거하자마자 앱은 이전 "느린"코드로도 클릭 할 수있는 속도만큼 빠르게 작동합니다.
M Barbosa

당신은 내 하루를했다!
Nicolas Mastromarino

:) 당신은 절대 천재입니다.
Metin Ilhan

@batsheva 1KB 일 필요는 없습니다. 필요에 따라 더 선명한 이미지가 필요하고 더 높은 해상도를 사용할 수 있지만 다른 크기의 리소스 폴더로 분할해야합니다.
Sithu

61

나도 같은 문제가 있었다.
광산은 드로어 블에있는 배경 이미지를 사용하는 경우였습니다.이 특정 이미지는 약 130kB이며 내 안드로이드 앱의 스플래시 화면 및 홈 페이지에서 사용되었습니다.

해결책 -방금 특정 이미지를 드로어 블에서 drawables-xxx 폴더로 옮겼으며 백그라운드에서 점유 된 많은 메모리를 확보 할 수 있었고 건너 뛰는 프레임이 더 이상 건너 뛰지 않았습니다.

업데이트 백그라운드 드로어 블 파일을 저장하려면 'nodp'드로어 블 리소스 폴더를 사용하십시오.
밀도 한정 드로어 블 폴더 또는 드로어 블-노피가 우선합니까?


7
큰 배경 이미지를 드로어 블에서 mimap-xxxhdpi로 옮겼습니다.
bgplaya

당신은 많은 도움이되었습니다. 감사합니다
N.Droid

2
이 솔루션은 트릭을 수행하고 있습니다. drawable-xxxhdpi대신 폴더 를 drawable사용하여 사용 된 메모리를 크게 줄입니다 (약 70 % 적음). 또한 같은 크기의 화면은 DPI 크기가 다릅니다. 이들 사이의 화소의 비율이 ldpi = 1:0.75, mdpi = 1:1, hdpi = 1:1.5, xhdpi = 1:2, xxhdpi = 1:3, xxxhdpi = 1:4. 하여 사용하여 drawable-xxxhdpi폴더를 당신은 메모리와 CPU 사용량을 감소 어떤 장치의 화면 크기에 이미지를 다운 스케일 할 수 있습니다.
Timo Bähr

2
에서 이미지를 이동 drawable하여 drawable-nodpi응용 프로그램을 가져 오는 것을 방지합니다 Out of Memory Error.
Shruti

세상에 ... 고마워! 나는 drawable 폴더 내에 이미지가 있었고 이것은 내 앱을 지옥처럼 느리게 만들었습니다 (이미지는 100kb에 불과했지만! drawable-xxx 파일 (Android Drawable Importer 사용)을 생성 한 후 내 앱이 빠릅니다. 고마워요!
error1337

20

UI 스레드 지연의 또 다른 일반적인 원인은 SharedPreferences 액세스입니다. a PreferenceManager.getSharedPreferences및 기타 유사한 메소드를 처음 호출 하면 연관된 .xml 파일이 즉시 동일한 스레드에서 로드되고 구문 분석 됩니다 .

이 문제를 해결하는 좋은 방법 중 하나는 백그라운드 스레드에서 가능한 한 빨리 (예 : onCreateApplication 클래스에서) 시작된 SharedPreference로드를 트리거 하는 것입니다. 이런 식으로 기본 설정 개체는 사용하려는 시간에 따라 이미 구성되었을 수 있습니다.

불행히도, 때때로 초기 시작 단계 (예 : 초기 활동 또는 응용 프로그램 자체)에서 기본 설정 파일을 읽어야합니다. 이러한 경우 여전히을 사용하여 UI 정지를 피할 수 있습니다 MessageQueue.IdleHandler. 메인 스레드에서 수행해야 할 다른 모든 작업을 수행 한 다음 활동이 완전히 그려지면 IdleHandler를 설치하여 코드를 실행하십시오. 그 Runnable에서 너무 많은 그리기 작업을 지연시키지 않고 Choreographer를 불행하게 만들지 않고 SharedPreferences에 액세스 할 수 있어야합니다.


1
이 경우 commit () 대신 apply () 메소드를 선호해야합니다. apply () 메소드는 UI를 차단할 수 없습니다. 여기에서 볼 수 있습니다 developer.android.com/training/data-storage/shared-preferences
Emre Gürses

16

앱 성능을 향상 시키려면 다음 전략을 사용하십시오.

  • 가능하면 멀티 스레딩 프로그래밍을 사용하십시오. 스마트 폰에 하나의 코어가 있어도 성능 이점은 엄청납니다 (프로세서가 둘 이상인 경우 스레드가 다른 코어에서 실행될 수 있음). 앱 로직을 UI와 분리하는 것이 유용합니다. Java 스레드, AsyncTask 또는 IntentService를 사용하십시오. 이것을 확인하십시오 .
  • Android 개발 웹 사이트의 기타 성능 팁을 읽고 따르십시오. 여기를 확인하십시오 .

3
첫 번째 링크를 이용하려면 "... 유효한 계정이 있습니다 ..."가 필요합니다.
Chornge

9

나는 같은 문제가 있었다. 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>

8

나는 전문가가 아니지만 안드로이드 응용 프로그램에서 웹 서버로 데이터를 보내려고 할 때이 디버그 메시지를 받았습니다. AsyncTask 클래스를 사용하고 백그라운드에서 데이터 전송을 수행했지만 서버에서 결과 데이터를 다시 가져 오기 위해 UI를 동기화하는 AsyncTask 클래스의 get () 메서드를 사용하여 UI를 너무 오래 기다릴 수 있습니다. 따라서 내 조언은 앱이 모든 네트워크 지향 작업을 별도의 스레드에서 수행하도록하는 것입니다.


6

이미지 최적화 ... 100KB보다 큰 이미지는 사용하지 마십시오 ... 이미지를로드하는 데 너무 많은 CPU가 걸리고 앱이 중단됩니다.


4
자바 코드 또는 이미지를 자르기 위해 포토샵을 사용하여 이미지의 크기를 줄입니다. 또한 compressor.io를 사용하여 이미지를 압축
HarshitG

5

나는 같은 문제가 있었다. 내 경우에는 2 개의 중첩 상대 레이아웃이 있습니다. RelativeLayout은 항상 두 개의 측정 패스를 수행해야합니다. RelativeLayouts를 중첩하면 지수 측정 알고리즘을 얻게됩니다.


4

이것은 주로 메인 스레드에서 거대한 프로세스를 실행할 때 발생합니다. 200보다 작은 프레임을 건너 뛰어도 괜찮습니다. 건너 뛴 프레임이 200 개보다 많으면 응용 프로그램 UI 스레드 속도가 느려질 수 있습니다. 할 수있는 일은 worker thread라는 새로운 스레드에서 이러한 프로세스를 수행 한 다음 UI 스레드로 액세스하고 sth를 수행하려는 경우 (예 : 뷰, findView 등으로 작업 수행) 핸들러 또는 runOnUiThread를 사용할 수 있습니다 처리 결과를 표시하기 위해 (이것이 더 좋습니다). 이것은 절대적으로 문제를 해결합니다. 작업자 스레드를 사용하면 매우 유용하거나이 경우에는 사용해야합니다.


1

나는 같은 문제가 있었다. 다른 컴퓨터에서 코드를 실행하면 정상적으로 작동했습니다. 그러나 광산에서는 "응용 프로그램이 기본 스레드에서 너무 많은 작업을 수행하고있을 수 있습니다"라고 표시했습니다.

안드로이드 스튜디오를 다시 시작하여 문제를 해결했습니다 [파일-> 무효 캐시 / 재시작-> "유효하지 않은 후 다시 시작"클릭).


귀하의 솔루션이 왜 효과가 있었는지 모르겠습니다. 어쨌든 고마워
Bhuvanesh BS

1

필자의 경우 실수로 메소드에 중단 점을 설정했기 때문입니다. 메시지를 지우면 메시지가 사라지고 성능이 많이 향상되었습니다.


0

내 앱에도 같은 문제가있었습니다. 그러나 카드와 텍스트 목록을 표시하는 것 외에는하지 않았습니다. 백그라운드에서 실행되는 것이 없습니다. 그러나 조사 후 카드 배경에 설정된 이미지가 작지만 (350kb)이 문제를 일으키는 것으로 나타났습니다. 그런 다음 http://romannurik.github.io/AndroidAssetStudio/index.html을 사용하여 이미지를 9patch 이미지로 변환했습니다 .
이것은 나를 위해 일했습니다.


0

이 문제에 대해 많은 R & D를 수행 한 후 솔루션을 얻었습니다.

필자의 경우 2 초마다 실행되는 서비스를 사용하고 runonUIThread와 함께 문제가 있었지만 전혀 그렇지 않은지 궁금했습니다. 내가 찾은 다음 문제는 큰 앱에서 큰 이미지를 사용하고 있다는 것입니다.

이미지를 제거하고 새 이미지를 설정했습니다.

결론 :-코드를 살펴보면 사용중인 원시 파일이 크기가 큽니다.


0

먼저 경고를 읽으십시오. 메인 스레드에 더 많은 부하가 있다고 말합니다. 그래서 당신이해야 할 일은 스레드에서 더 많은 작업으로 함수를 실행하는 것입니다.


-1

그리드 레이아웃에서 많은 drawable png 파일을 사용하는 앱을 개발하는 동안 동일한 문제가 발생했습니다. 나는 또한 가능한 한 코드를 최적화하려고 노력했지만 .. 그것은 나에게 적합하지 않았다. 그런 다음 그 png의 크기를 줄이려고 노력했다. 드로어 블 자원의 크기

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.