วิธีที่คุณจัดการลำดับชั้นของ
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
อื่นๆ องค์ประกอบ
ของเฟรมเวิร์กจะดำเนินการตามลำดับต่อไปนี้
- เรียกใช้การส่งผ่านเลย์เอาต์และการวัดผล ซึ่งในระหว่างนี้เฟรมเวิร์กจะคำนวณออบเจ็กต์ย่อยแต่ละรายการ ตำแหน่งและขนาดตามคำขอของผู้เผยแพร่โฆษณาย่อยแต่ละราย
- ใช้ข้อมูลนี้โดยคำนึงถึงน้ำหนักออบเจ็กต์ เพื่อหาตำแหน่งที่เหมาะสมของ มุมมองที่สัมพันธ์กัน
- ส่งเลย์เอาต์ลำดับที่ 2 เพื่อสรุปออบเจ็กต์ ตำแหน่ง
- ย้ายไปยังขั้นตอนถัดไปของกระบวนการแสดงผล
ยิ่งลำดับชั้นของการแสดงผลหลายระดับมากเท่าใด โอกาสที่จะเกิดความเสียหายต่อประสิทธิภาพก็จะมากขึ้นเท่านั้น
ดังที่กล่าวไว้ก่อนหน้านี้ โดยทั่วไป 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
![](https://developer.android.com/static/topic/performance/images/lint-inspect-code.png?authuser=5&hl=th)
ข้อมูลเกี่ยวกับรายการเลย์เอาต์ต่างๆ จะปรากฏในส่วน Android > Lint > ประสิทธิภาพ หากต้องการดูรายละเอียดเพิ่มเติม ให้คลิกแต่ละรายการเพื่อขยายและแสดงข้อมูลเพิ่มเติมในแผง ทางด้านขวาของหน้าจอ รูปที่ 2 แสดงตัวอย่างข้อมูลแบบขยาย
![](https://developer.android.com/static/topic/performance/images/lint-display.png?authuser=5&hl=th)
การคลิกที่รายการจะแสดงปัญหาที่เกี่ยวข้องกับรายการนั้นในบานหน้าต่างด้านขวา
หากต้องการทำความเข้าใจเพิ่มเติมเกี่ยวกับหัวข้อและปัญหาเฉพาะในด้านนี้ โปรดดูที่ 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
และยังมีฟีเจอร์เพิ่มเติมเพื่อช่วยในการสร้าง
รูปแบบที่เรียบง่ายและมีประสิทธิภาพมากขึ้น