ลำดับชั้นของประสิทธิภาพและมุมมอง

วิธีที่คุณจัดการลำดับชั้นของ View วัตถุอาจส่งผลกระทบอย่างมาก ประสิทธิภาพของแอป หน้านี้จะอธิบายวิธีประเมินว่าลำดับชั้นการแสดงผลของคุณช้าลงหรือไม่ แอปของคุณใช้งานไม่ได้ และเสนอกลยุทธ์บางอย่างในการแก้ไขปัญหาที่อาจเกิดขึ้น

หน้านี้มุ่งเน้นที่การปรับปรุงเลย์เอาต์ที่อิงตาม View สําหรับข้อมูลเกี่ยวกับการปรับปรุง ประสิทธิภาพของ Jetpack Compose โปรดดู Jetpack Compose ประสิทธิภาพ

ประสิทธิภาพเลย์เอาต์และการวัดผล

ไปป์ไลน์การแสดงผลจะมีขั้นตอนเลย์เอาต์และการวัด ซึ่งในระหว่างนี้ระบบ วางตำแหน่งรายการที่เกี่ยวข้องในลำดับชั้นการแสดงผลของคุณอย่างเหมาะสม ส่วนการวัดผลของข้อมูลนี้ สถานะจะกำหนดขนาดและขอบเขตของออบเจ็กต์ View รายการ ส่วนเลย์เอาต์ กำหนดตำแหน่งบนหน้าจอเพื่อวางวัตถุ View

ขั้นตอนไปป์ไลน์ทั้ง 2 ขั้นตอนนี้มีค่าใช้จ่ายต่อการดูหรือเลย์เอาต์ที่ประมวลผลเล็กน้อย ส่วนใหญ่ของ ค่าใช้จ่ายนี้จะต่ำมากและไม่ส่งผลกระทบต่อประสิทธิภาพอย่างเห็นได้ชัด อย่างไรก็ตาม มีโอกาสที่ เมื่อแอปเพิ่มหรือนำออบเจ็กต์ View รายการออก เช่น วันที่ RecyclerView จะรีไซเคิลเนื้อหาเหล่านั้น หรือนำมาใช้ซ้ำ ค่าใช้จ่ายอาจสูงขึ้นหากต้องใช้ออบเจ็กต์ View เพื่อพิจารณาปรับขนาดให้เป็นไปตามข้อจำกัด ตัวอย่างเช่น หากแอปเรียก SetText() บนออบเจ็กต์ View ที่รวมข้อความไว้ View อาจต้องปรับขนาด

หากกรณีเช่นนี้ใช้เวลานานเกินไป อาจทำให้เฟรมไม่สามารถแสดงผลภายในจำนวนครั้งที่อนุญาต 16 มิลลิวินาที ซึ่งอาจทำให้เฟรมลดลงและทำให้ภาพเคลื่อนไหวติดขัด

เนื่องจากคุณย้ายการดำเนินการเหล่านี้ไปยังเทรดผู้ปฏิบัติงานไม่ได้ แอปของคุณจึงต้องประมวลผลการดำเนินการเหล่านั้น เทรดหลัก คุณควรเพิ่มประสิทธิภาพให้เทรดหลักเพื่อให้ใช้เวลาน้อยที่สุด

จัดการเลย์เอาต์ที่ซับซ้อน

เลย์เอาต์ของ Android ให้คุณฝังออบเจ็กต์ UI ใน ลำดับชั้นการแสดงผล การซ้อนนี้ยังอาจกำหนดค่าเลย์เอาต์ด้วย เมื่อแอปประมวลผลออบเจ็กต์ สำหรับการออกแบบ แอปก็จะดำเนินการเหมือนกันกับองค์ประกอบย่อยทั้งหมดของเค้าโครง

สำหรับเลย์เอาต์ที่ซับซ้อน บางครั้งอาจต้องเสียค่าใช้จ่ายเฉพาะครั้งแรกที่ระบบคำนวณ เลย์เอาต์ เช่น เมื่อแอปของคุณนำรายการที่ซับซ้อนมารีไซเคิลใน RecyclerView ระบบจะต้องจัดวางวัตถุทั้งหมด อีกตัวอย่างหนึ่ง การเปลี่ยนแปลงเพียงเล็กน้อยสามารถ เผยแพร่เชนไปยังระดับบนจนกว่าจะไปถึงออบเจ็กต์ที่ไม่ส่งผลต่อขนาดของ ผู้ปกครอง

สาเหตุทั่วไปที่ทำให้เลย์เอาต์ใช้เวลานานคือเมื่อลำดับชั้นของออบเจ็กต์ View ซ้อนกันอยู่ภายใน ออบเจ็กต์เลย์เอาต์ที่ซ้อนกันแต่ละรายการจะเพิ่มค่าใช้จ่ายให้กับขั้นตอนเลย์เอาต์ ที่ราบเรียบกว่า ลำดับชั้นก็จะยิ่งใช้เวลาน้อยลงในขั้นตอนของเลย์เอาต์

เราขอแนะนำให้ใช้ เครื่องมือแก้ไขการออกแบบเพื่อสร้าง ConstraintLayout แทนที่จะเป็น RelativeLayoutหรือ LinearLayoutตามที่เป็น จะมีประสิทธิภาพมากกว่าและลดการซ้อนของเลย์เอาต์ อย่างไรก็ตาม สำหรับการจัดวางแบบง่ายที่ จะประสบความสำเร็จได้โดยใช้ FrameLayout เราขอแนะนำ ด้วย FrameLayout

หากใช้ชั้นเรียน RelativeLayout คุณอาจได้ระดับเดียวกันนี้ โดยใช้ต้นทุนที่ต่ำลงโดยใช้การดู LinearLayout แบบซ้อนและไม่ได้ถ่วงน้ำหนักแทน อย่างไรก็ตาม หากคุณใช้การดู LinearLayout แบบซ้อน (ถ่วงน้ำหนัก) ค่าใช้จ่ายสำหรับเลย์เอาต์จะสูงกว่ามาก เพราะต้องใช้เลย์เอาต์หลายแบบ ตามที่อธิบายไว้ในส่วนถัดไป

นอกจากนี้ เราขอแนะนำให้ใช้ RecyclerView แทน ListView เนื่องจากสามารถรีไซเคิล การจัดวางของแต่ละรายการ ซึ่งมีประสิทธิภาพมากกว่าและช่วยเพิ่มการเลื่อนตำแหน่ง ด้านประสิทธิภาพ

การเก็บภาษีซ้อน

โดยปกติแล้ว เฟรมเวิร์กจะดำเนินการเลย์เอาต์หรือขั้นตอนการวัดเพียงครั้งเดียว อย่างไรก็ตาม บางกรณีรูปแบบที่ซับซ้อน เฟรมเวิร์กอาจต้องทำซ้ำหลายครั้งสำหรับส่วนต่างๆ ของ ลำดับชั้นที่ต้องมีการผ่านหลายใบเพื่อแก้ไขก่อนที่จะวางตำแหน่งองค์ประกอบในท้ายที่สุด กำลังมี ในการดำเนินการทำซ้ำการจัดวางและวัดผลมากกว่า 1 ครั้งเรียกว่า การทำซ้ำ ภาษีอากร

ตัวอย่างเช่น เมื่อคุณใช้คอนเทนเนอร์ RelativeLayout ซึ่งให้คุณจัดตำแหน่ง View วัตถุที่สัมพันธ์กับตำแหน่งของวัตถุ View อื่นๆ องค์ประกอบ ของเฟรมเวิร์กจะดำเนินการตามลำดับต่อไปนี้

  1. เรียกใช้การส่งผ่านเลย์เอาต์และการวัดผล ซึ่งในระหว่างนี้เฟรมเวิร์กจะคำนวณออบเจ็กต์ย่อยแต่ละรายการ ตำแหน่งและขนาดตามคำขอของผู้เผยแพร่โฆษณาย่อยแต่ละราย
  2. ใช้ข้อมูลนี้โดยคำนึงถึงน้ำหนักออบเจ็กต์ เพื่อหาตำแหน่งที่เหมาะสมของ มุมมองที่สัมพันธ์กัน
  3. ส่งเลย์เอาต์ลำดับที่ 2 เพื่อสรุปออบเจ็กต์ ตำแหน่ง
  4. ย้ายไปยังขั้นตอนถัดไปของกระบวนการแสดงผล

ยิ่งลำดับชั้นของการแสดงผลหลายระดับมากเท่าใด โอกาสที่จะเกิดความเสียหายต่อประสิทธิภาพก็จะมากขึ้นเท่านั้น

ดังที่กล่าวไว้ก่อนหน้านี้ โดยทั่วไป ConstraintLayout จะมีประสิทธิภาพมากกว่าส่วนอื่นๆ ยกเว้น FrameLayout มีโอกาสน้อยลงที่จะนำไปสู่การใช้เลย์เอาต์แบบต่างๆ ทำให้ไม่จำเป็นต้องซ้อนเลย์เอาต์

คอนเทนเนอร์อื่นที่ไม่ใช่ RelativeLayout อาจเพิ่มการเก็บภาษีซ้อนเช่นกัน สำหรับ ตัวอย่าง:

  • มุมมอง LinearLayout อาจส่งผลให้เกิดผ่าน 2 เลย์เอาต์และการวัดผลหากคุณสร้าง ให้เป็นแนวนอน อาจมีการแสดงบัตรผ่านแบบ 2 รูปแบบและวัดผลในแนวตั้งด้วยหากคุณ เพิ่ม measureWithLargestChild, ในกรณีนี้ เฟรมเวิร์กอาจต้องส่งขั้นตอนที่สองเพื่อแก้ไขขนาดที่เหมาะสม ออบเจ็กต์
  • นอกจากนี้ GridLayout อนุญาตการกำหนดตำแหน่งแบบสัมพัทธ์ แต่โดยปกติจะหลีกเลี่ยงการเก็บภาษีซ้อนด้วยการประมวลผลฟิลด์ ความสัมพันธ์ระหว่างตำแหน่ง ในการรับชมของเด็ก แต่ถ้าเค้าโครงใช้น้ำหนักหรือเติมด้วยแท็ก Gravity คลาส ข้อดีของ การประมวลผลล่วงหน้าจะหายไป และเฟรมเวิร์กอาจต้องทำงานหลายครั้งหากคอนเทนเนอร์ เป็นRelativeLayout

บัตรผ่านที่มีเลย์เอาต์และการวัดผลหลายรายการไม่จำเป็นต้องเป็นภาระด้านประสิทธิภาพ อย่างไรก็ตาม พวกเขาอาจ จะกลายเป็นภาระถ้าอยู่ผิดที่ ระมัดระวังในสถานการณ์อย่างใดอย่างหนึ่งต่อไปนี้ เงื่อนไขที่ใช้กับคอนเทนเนอร์ของคุณ:

  • หรือเป็นองค์ประกอบรูทในลำดับชั้นการแสดงผล
  • มีลําดับชั้นของมุมมองเชิงลึกอยู่ด้านล่าง
  • มีหลายกรณีที่โฆษณาปรากฏบนหน้าจอ ซึ่งคล้ายกับหน้าเว็บแบบเด็กใน ออบเจ็กต์ ListView รายการ

วิเคราะห์ปัญหาลำดับชั้นการแสดงผล

ประสิทธิภาพของเลย์เอาต์เป็นปัญหาที่ซับซ้อนซึ่งพบได้หลายแง่มุม เครื่องมือต่อไปนี้สามารถช่วยคุณได้ ดูว่าจุดคอขวดด้านประสิทธิภาพเกิดขึ้นที่ใด เครื่องมือบางอย่างให้ข้อมูลที่แน่ชัดน้อยกว่า แต่สามารถให้คำแนะนำที่เป็นประโยชน์ได้

แปร์เฟตโต

Perfetto เป็นเครื่องมือที่ให้ข้อมูลเกี่ยวกับประสิทธิภาพ คุณสามารถเปิดการติดตาม Android ใน Perfetto ได้ UI

การแสดงผล GPU ตามโปรไฟล์

การแสดงผล GPU ของโปรไฟล์ในอุปกรณ์ ซึ่งพร้อมใช้งานในอุปกรณ์ที่ใช้ Android 6.0 (API ระดับ 23) ขึ้นไปจะช่วยให้ ข้อมูลที่เป็นรูปธรรมเกี่ยวกับจุดคอขวดด้านประสิทธิภาพ เครื่องมือนี้ช่วยให้คุณเห็นว่า ขั้นตอนต่างๆ ของการจัดวางและการวัดผล เฟรมของการแสดงผล ข้อมูลนี้สามารถช่วยคุณวินิจฉัยปัญหาด้านประสิทธิภาพรันไทม์และช่วยให้คุณ ระบุปัญหาเลย์เอาต์และการวัดผลที่คุณต้องจัดการ

ในการแสดงข้อมูลที่บันทึกในรูปแบบกราฟิก การแสดงผล GPU ของโปรไฟล์จะใช้สี สีน้ำเงินเพื่อแสดงเวลาของเลย์เอาต์ สําหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้เครื่องมือนี้ โปรดดู ความเร็วในการแสดงผล GPU ของโปรไฟล์

ขุยผ้า

เครื่องมือ Lint ของ Android Studio จะช่วยให้คุณทำความเข้าใจเกี่ยวกับ ความด้อยประสิทธิภาพในลำดับชั้นการแสดงผล หากต้องการใช้เครื่องมือนี้ เลือก วิเคราะห์ > ตรวจสอบโค้ด เช่น ที่แสดงในรูปที่ 1

วันที่
รูปที่ 1 เลือกตรวจสอบโค้ดใน Android Studio

ข้อมูลเกี่ยวกับรายการเลย์เอาต์ต่างๆ จะปรากฏในส่วน Android > Lint > ประสิทธิภาพ หากต้องการดูรายละเอียดเพิ่มเติม ให้คลิกแต่ละรายการเพื่อขยายและแสดงข้อมูลเพิ่มเติมในแผง ทางด้านขวาของหน้าจอ รูปที่ 2 แสดงตัวอย่างข้อมูลแบบขยาย

วันที่
รูปที่ 2 การดูข้อมูลเกี่ยวกับปัญหาเฉพาะในเครื่องมือ Lint ระบุตัวตน

การคลิกที่รายการจะแสดงปัญหาที่เกี่ยวข้องกับรายการนั้นในบานหน้าต่างด้านขวา

หากต้องการทำความเข้าใจเพิ่มเติมเกี่ยวกับหัวข้อและปัญหาเฉพาะในด้านนี้ โปรดดูที่ Lint

เครื่องมือตรวจสอบเลย์เอาต์

เครื่องมือตรวจสอบเลย์เอาต์ของ Android Studio มี การแสดงภาพลำดับชั้นของแอป วิธีที่ดีคือการสำรวจลำดับชั้น แอปของคุณ โดยให้เห็นภาพที่ชัดเจนเกี่ยวกับห่วงโซ่ระดับบนสุดของมุมมองนั้นๆ และช่วยให้คุณ ตรวจสอบเลย์เอาต์ที่แอปสร้างขึ้น

มุมมองที่เครื่องมือตรวจสอบเลย์เอาต์นำเสนอก็สามารถช่วยระบุปัญหาด้านประสิทธิภาพที่เกิดจาก ในการเก็บภาษีซ้อน และยังให้คุณระบุเลย์เอาต์แบบซ้อนกันแบบ Deep Link หรือ พื้นที่เลย์เอาต์ที่มีองค์ประกอบย่อยจำนวนมากที่ซ้อนกันอยู่ ซึ่งอาจเป็นแหล่งที่มาของต้นทุนด้านประสิทธิภาพ ใน ในกรณีเช่นนี้ ขั้นตอนการจัดวางและการวัดผลอาจมีต้นทุนสูงและทำให้เกิดปัญหาด้านประสิทธิภาพ

สำหรับข้อมูลเพิ่มเติม โปรดดูแก้ไขข้อบกพร่องการออกแบบด้วย เครื่องมือตรวจสอบเลย์เอาต์และการตรวจสอบเลย์เอาต์

แก้ไขปัญหาลําดับชั้นของมุมมอง

แนวคิดพื้นฐานของการแก้ปัญหาด้านประสิทธิภาพที่เกิดจากลำดับชั้นการแสดงผลช่วย อาจทำได้ยากในทางปฏิบัติ การป้องกันไม่ให้ลำดับชั้นการดูกำหนดบทลงโทษด้านประสิทธิภาพมีดังนี้ ในการแยกลำดับชั้นการแสดงผล และลดการจัดเก็บภาษีซ้อน ส่วนนี้จะกล่าวถึงกลยุทธ์ ในการบรรลุเป้าหมายเหล่านี้

นำเลย์เอาต์ที่ซ้อนกันที่ซ้ำซ้อนออก

ConstraintLayout เป็นไลบรารี Jetpack ที่มีกลไกต่างๆ จำนวนมากสำหรับการวางตำแหน่งมุมมองภายใน เลย์เอาต์ การดําเนินการนี้จะลดความจำเป็นในการฝัง ConstaintLayout รายการเดียว และช่วยปรับมุมมองให้แบนราบได้ ลำดับชั้น โดยปกติแล้วจะแยกลำดับชั้นได้ง่ายกว่าโดยใช้ ConstraintLayout เมื่อเปรียบเทียบ กับเลย์เอาต์ประเภทอื่นๆ

นักพัฒนาแอปมักจะใช้เลย์เอาต์ที่ซ้อนกันเกินความจำเป็น ตัวอย่างเช่น คอนเทนเนอร์ RelativeLayout อาจมีลูกเดียวที่เป็น คอนเทนเนอร์ RelativeLayout การซ้อนนี้ซ้ำซ้อนและเพิ่มค่าใช้จ่ายที่ไม่จำเป็นให้กับ ลำดับชั้นการแสดงผล Lint จะแจ้งปัญหานี้ให้คุณได้ ซึ่งจะลดเวลาในการแก้ไขข้อบกพร่อง

ใช้การรวมหรือรวม

สาเหตุที่พบบ่อยของเลย์เอาต์ที่ซ้อนกันซ้ำซ้อน <include> แท็ก ตัวอย่างเช่น คุณอาจกำหนดการออกแบบที่นำมาใช้ใหม่ได้ดังต่อไปนี้:

<LinearLayout>
    <!-- some stuff here -->
</LinearLayout>

คุณอาจเพิ่มแท็ก <include> เพื่อเพิ่มรายการต่อไปนี้ไปยังระดับบนสุด คอนเทนเนอร์:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/app_bg"
    android:gravity="center_horizontal">

    <include layout="@layout/titlebar"/>

    <TextView android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:text="@string/hello"
              android:padding="10dp" />

    ...

</LinearLayout>

การรวมก่อนหน้าจะซ้อนเลย์เอาต์แรกโดยไม่จำเป็นภายในเลย์เอาต์ที่ 2

<merge> จะช่วยป้องกันปัญหานี้ได้ สำหรับข้อมูลเกี่ยวกับแท็กนี้ โปรดดู ใช้ <merge>

ใช้เลย์เอาต์ที่ราคาถูกลง

คุณอาจปรับรูปแบบเลย์เอาต์ที่มีอยู่ไม่ได้เพื่อไม่ให้มีความซ้ำซ้อน เลย์เอาต์ ในบางกรณี วิธีแก้ไขเพียงอย่างเดียวอาจเป็นการปรับลำดับชั้นโดยการเปลี่ยนไปใช้ ประเภทเลย์เอาต์ที่แตกต่างไปโดยสิ้นเชิง

ตัวอย่างเช่น คุณอาจพบว่า TableLayout มีค่าเท่ากัน เป็นเค้าโครงที่ซับซ้อนมากขึ้นโดยมีการขึ้นต่อกันหลายตำแหน่ง ห้องสมุด Jetpack ConstraintLayout มีฟังก์ชันที่คล้ายกับ RelativeLayout และยังมีฟีเจอร์เพิ่มเติมเพื่อช่วยในการสร้าง รูปแบบที่เรียบง่ายและมีประสิทธิภาพมากขึ้น