Android 개발을 위한 성능 최적화: 전환 드로잉 솔루션

1. 전환 도면

화면의 특정 픽셀이 한 프레임에 여러 번 반복적으로 그려지는 전환 드로잉입니다.
아래 이미지는 함께 떨어지는 여러 카드를 보여주지만 첫 번째 카드만 완전히 보입니다. 뒤에 있는 카드는 부분적으로만 보입니다. 그러나 Android 시스템은 뽑을 때 아래쪽 카드를 뽑은 다음 위쪽 카드를 뽑습니다. 그러나 실제로는 아래쪽 카드의 보이지 않는 부분은 그릴 필요가 없으며 보이는 부분만 그리면 됩니다.

전환 도면의 수준에 따라 다음과 같이 나눌 수 있습니다.

  • 전환 없이 그리기(픽셀은 한 번만 그려짐)
  • 트랜지션 드로우 x1(픽셀이 두 번 그려짐)
  • 트랜지션 드로우 x2(픽셀이 세 번 그려짐)
  • 오버드로 x3(픽셀이 4번 그려짐)
  • 오버드로 x4+(픽셀이 5번 이상 그려짐)

2. 애플리케이션의 전환 도면 보기

방법 1: 개발자 옵션을 통해 GPU 전환 렌더링 디버깅 활성화

Android 휴대폰의 개발자 옵션에는 "debug GPU overdrawing" 옵션이 있습니다.

클릭한 후 "전환 그리기 영역 표시"를 선택합니다.

방법 2: adb 명령을 통해 GPU 전환 렌더링 디버깅 활성화

물론 시스템 설정을 매번 입력하는 것이 번거롭다면 adb 명령을 사용하여 켜고 끌 수 있습니다:
"Debug GPU overdrawing" 켜기:

adb shell setprop debug.hwui.overdraw show

"GPU 오버드로 디버그"를 끕니다.

adb shell setprop debug.hwui.overdraw false

명령을 실행한 후 현재 개발 중인 애플리케이션을 다시 시작해야 할 수도 있습니다.

색상 및 전환 도면:

  • 기본 색상: 오버드로 없음
  • 파란색: 1 오버드로
  • 녹색: 2 오버드로
  • 분홍색: 오버드로 3회
  • 빨간색: 4개 이상의 오버드로

정상적인 개발에서 분홍색 이상의 전환 그리기 상황이 있는 경우. 오버 드로잉에 대한 지침도 매우 엄격합니다. 최적화가 필요합니다.

3. 트랜지션 드로잉 최적화

1. 활동과 함께 제공되는 기본 배경색을 제거합니다.

다음과 같이 Android 소스 코드에서 테마 테마를 봅니다.

<style name="Theme">
    ...
    <!-- Window attributes -->
    <item name="windowBackground">@drawable/screen_background_selector_dark</item>
    ...
</style>

즉, Theme의 스타일을 상속받게 되면 기본적으로 새로운 Activity를 생성할 때 배경이 생깁니다. 정상적인 상황에서는 많은 인터페이스에 실제로 배경이 필요하지 않습니다.

다음은 화웨이 내장 날씨 APP의 홈페이지입니다.텍스트와 아이콘이 녹색임을 알 수 있습니다.표면은 이미 세 번째 레이어에 그려져 있습니다.그 뒤에 있는 날씨 지도는 레이어이고 텍스트는 다른 레이어입니다. 정상입니다. 레이어가 2개만 있어야 한다는 것, 즉 텍스트와 아이콘이 파란색이어야 한다는 것입니다.

그런 다음 이 추가 레이어는 활동과 함께 제공되는 배경색이어야 합니다. 테마에 설정되어 있습니다.

AppTheme에서 배경색을 제거하기만 하면 됩니다.

<style name="AppTheme" parent="android:Theme.Light.NoTitleBar">
    <item name="android:windowBackground">@null</item>
</style>

또는 액티비티의 onCreate 메소드에서:

getWindow().setBackgroundDrawable(null);

2. Canvas의 clipRect 및 clipPath 메서드를 사용하여 View의 그리기 영역을 제한합니다.

Activity는 Canvas인 Canvas에 해당한다.Canvas의 개념은 화판이다.이 Canvas는 많은 API를 제공한다.Canvas의 API를 호출하여 Canvas에 몇 가지 작업을 그리고 그릴 수 있다.clipRect 메서드는 다음과 같다. 캔버스를 자르는 데 사용됩니다.Rect 개체로 설명되는 직사각형 영역입니다. clipRect를 호출한 후 캔버스의 그릴 수 있는 영역은 Rect에서 지정한 사각형 영역과 같은 크기로 축소됩니다. 모든 그리기는 이 사각형으로 제한됩니다. 여기서 자르기 개념은 PS의 개념과 유사합니다.

일반적인 예인 서랍 레이아웃에서 Netease Cloud Music을 찾아 수술을 했습니다.

이미지.png

왼쪽 서랍이 열렸을 때 서랍 레이아웃이 뒷면 레이아웃과 겹치는 것을 관찰하세요. 이때 전체 화면의 절반 이상이 빨간색으로 변하고 전환 그림이 심각합니다.

서랍 레이아웃이 팝업되면 서랍 레이아웃이 불투명합니다. 즉, 서랍 레이아웃 뒤의 콘텐츠 레이아웃을 그릴 필요가 없지만 NetEase Cloud가 이를 그려서 서랍 레이아웃이 있는 영역의 픽셀이 여러 번 그린다.

Google은 공식적으로 android.support.v4.widget 패키지 아래에 DrawerLayout.Java 클래스를 가지고 있습니다. 서랍 레이아웃을 구현하는 데 사용됩니다. 이 클래스는 drawChild 메서드를 재정의합니다.

@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
    final int height = getHeight();
    // 判断是否是内容视图
    final boolean drawingContent = isContentView(child);
    int clipLeft = 0, clipRight = getWidth();

    // 记录当前画布信息
    final int restoreCount = canvas.save();
    if (drawingContent) {
        // 只有在绘制内容视图时才进行裁切
        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View v = getChildAt(i);
            if (v == child || v.getVisibility() != VISIBLE ||
                    !hasOpaqueBackground(v) || !isDrawerView(v) ||
                    v.getHeight() < height) {
                // 如果child是内容视图/视图不可见/视图背景透明/不是抽屉视图/child高度小于父布局高度
                // 则不做画布裁切
                continue;
            }

            if (checkDrawerViewAbsoluteGravity(v, Gravity.LEFT)) {
                // 盒子在左侧时裁切的left和right
                final int vright = v.getRight();
                if (vright > clipLeft) clipLeft = vright;
            } else {
                // 盒子在右侧时裁切的的left和right
                final int vleft = v.getLeft();
                if (vleft < clipRight) clipRight = vleft;
            }
        }
        // 裁切画布
        canvas.clipRect(clipLeft, 0, clipRight, getHeight());
    }
    // 绘制子视图
    final boolean result = super.drawChild(canvas, child, drawingTime);
    // 回复到裁切之前的画布
    canvas.restoreToCount(restoreCount);
}

하위 뷰를 그리기 위해 ViewGroup 클래스의 dispatchDraw 메서드에서 drawChild 메서드가 호출되는데, 모든 자식 뷰가 그려지기 전에 drawChild 메서드가 호출되기 때문에 DrawerLayout 클래스는 이 메서드를 다시 작성하지만 여기서는 콘텐츠 영역 뷰만 잘라야 합니다. 컨텐츠 영역 보기에서 서랍 보기의 위치 정보 획득 서랍 보기가 보이고 배경이 불투명하며 서랍의 높이가 상위 레이아웃의 높이와 일치하면 왼쪽의 위치 정보를 얻고, 캔버스에서 서랍 보기의 위쪽, 오른쪽 및 아래쪽 가장자리. 그런 다음 컨텐츠 뷰에서 막히지 않은 부분을 잘라서 잘라낸 후 잘린 캔버스를 자식 뷰에 넘겨서 그리기 때문에 컨텐츠 영역은 잘린 영역에만 그려지고 다른 영역은 그려지지 않습니다. .그리다.

하위 View를 그린 후에는 Canvas를 잘라내기 전 상태로 복원합니다. Window 아래의 모든 View는 동일한 Canvas를 사용하므로 다른 하위 View가 사용하려면 상태를 복원해야 합니다.

DrawerLayout에 의해 구현되는 시스템의 "다운로드" 앱을 살펴보겠습니다.

응용 프로그램에서 콘텐츠 영역이 빨간색이지만 서랍 보기를 꺼낸 후 서랍 보기의 전환 그림은 콘텐츠 영역의 방해받지 않는 부분보다 작습니다.

3. ImageView의 배경과 imageDrawable 겹침

Android에서는 모든 뷰가 배경을 설정할 수 있습니다. 배경을 설정하는 것 외에도 ImageView는 ImageDrawable을 설정할 수도 있습니다.

개발하다 보면 그림을 표시해야 하는 경우가 종종 있는데 그림을 불러오기 전에 기본 그림을 표시하는 것이 보통인데 기본 배경 그림은 ImageView의 background 속성을 이용하여 설정하는 경우가 많으며 imageDrawable을 사용한다. 로드할 그림을 설정합니다. 이로 인해 문제가 발생하는데, 이미지가 페이지에 로드되면 기본 배경 이미지가 차단되지만 여전히 그려야 하므로 전환 드로잉이 발생합니다.

해결 방법은 imageDrawable 메서드를 통해 배경 이미지와 실제 로드된 이미지를 모두 설정하는 것 입니다.

4. 요약

  • Android에서 윈도우는 Canvas에 해당하며, 윈도우 아래의 모든 뷰(View/ViewGroup)는 동일한 캔버스를 사용하며, 뷰 트리의 부모 노드는 하위 뷰의 View.draw를 호출하기 전에 Canvas를 잘라냅니다. 화면에서 View가 차지하는 직사각형 영역이므로 View의 경계를 넘어선 내용이 잘립니다.

  • 트랜지션 그리기 값의 한 픽셀이 여러 번 그려지므로 그림이나 배경색이 겹치지 않는지 확인하면 됩니다. 올바른 방법은 배경과 View의 겹침 영역을 최소화하는 것입니다. 겹치는 경우 캔버스의 clipRect를 사용하여 자릅니다.

  • 뷰 트리의 순회 프로세스를 줄이기 위해 뷰의 깊이를 최소화합니다.

마침내

마지막으로 프로그래머에게는 배워야 할 지식 콘텐츠와 기술이 너무 많습니다. 환경에 의해 도태되지 않으려면 끊임없이 자신을 개선해야 합니다. 우리는 항상 환경이 아닌 환경에 적응해 왔습니다 . 우리에게 적응하기 위해. !

모두가 포괄적이고 명확한 방식으로 성능 최적화를 더 잘 이해할 수 있도록 관련 핵심 정보를 준비했습니다(기본 논리로 돌아가기).https://qr18.cn/FVlo89

성능 최적화 핵심 사항:https://qr18.cn/FVlo89

시작 최적화

메모리 최적화

UI

최적화 네트워크 최적화

비트맵 최적화 및 이미지 압축 최적화 : 다중 스레드 동시성 최적화 및 데이터 전송 효율성 최적화 볼륨 패키지 최적화https://qr18.cn/FVlo89




"Android 성능 모니터링 프레임워크":https://qr18.cn/FVlo89

"안드로이드 프레임워크 학습 매뉴얼":https://qr18.cn/AQpN4J

  1. 부팅 초기화 프로세스
  2. 부팅 시 Zygote 프로세스 시작
  3. 부팅 시 SystemServer 프로세스 시작
  4. 바인더 드라이버
  5. AMS 시작 프로세스
  6. PMS의 시작 프로세스
  7. 런처 시작 프로세스
  8. Android의 4가지 주요 구성요소
  9. Android 시스템 서비스 - 입력 이벤트 분배 프로세스
  10. Android 기본 렌더링 화면 새로 고침 메커니즘 소스 코드 분석
  11. Android 소스 코드 분석 실습

추천

출처blog.csdn.net/weixin_61845324/article/details/132351467