ทำไมน้ำหนักที่ซ้อนกันถึงไม่ดีสำหรับประสิทธิภาพ ทางเลือก?


160

ฉันเขียนไฟล์เลย์เอาต์สองชุดที่ฉันใช้layout_weightคุณลักษณะเพื่อสร้างอัตราส่วนระหว่างมุมมองที่แตกต่างกัน

เมื่อถึงจุดหนึ่งฉันเริ่มได้รับคำเตือนที่เป็นขุยเกี่ยวกับน้ำหนักที่ซ้อนกัน

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

ขอบคุณ!


2
โพสต์ที่ยอดเยี่ยมสำหรับผู้พัฒนาเลย์เอา
Muhammad Babar

คำตอบ:


140

น้ำหนักแบบซ้อนไม่ดีต่อประสิทธิภาพเนื่องจาก:

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

เป็นการดีกว่าที่จะใช้RelativeLayout s และปรับมุมมองของคุณตามตำแหน่งของมุมมองอื่น ๆ โดยไม่ใช้ค่า dpi ที่เฉพาะเจาะจง


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

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

รูปแบบสัมพัทธ์อาจไม่ทำงาน ในกรณีที่คุณต้องสร้างวิดเจ็ตตามสัดส่วน
Abdurakhmon

67

อัปเดต: ดังที่เราทราบเปอร์เซ็นต์ไลบรารีสนับสนุนเลิกใช้จาก API ระดับ 26 ConstraintLayoutเป็นวิธีใหม่ในการบรรลุโครงสร้าง xml แบบเดียวกัน

อัพเดทโครงการ Github

ตัวอย่างที่อัปเดต:

<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/fifty_thirty"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#ffff8800"
        android:gravity="center"
        android:text="@string/fifty_fifty_text"
        android:textColor="@android:color/white"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintHeight_percent="0.5"
        android:textSize="25sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.5" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#ffff5566"
        android:gravity="center"
        android:text="@string/fifty_fifty_text"
        android:textColor="@android:color/white"
        android:textSize="25sp"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintHeight_percent="0.5"
        app:layout_constraintLeft_toRightOf="@id/fifty_thirty"
        app:layout_constraintTop_toBottomOf="@id/fifty_thirty"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.5" />

</android.support.constraint.ConstraintLayout>

อัปเดต:ห้องสมุดสนับสนุนร้อยละข่าวดีสำหรับ Android แก้ปัญหาประสิทธิภาพการทำงานของเราและถ่วงน้ำหนักซ้อนกันLinearLayout

compile 'com.android.support:percent:23.0.0'

สาธิตที่นี่

พิจารณาเค้าโครงที่เรียบง่ายนี้เพื่อแสดงให้เห็นถึงสิ่งเดียวกัน

ร้อยละสนับสนุนการสาธิต libray

<android.support.percent.PercentRelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/fifty_huntv"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#ff7acfff"
        android:text="20% - 50%"
        android:textColor="@android:color/white"
        app:layout_heightPercent="20%"
        app:layout_widthPercent="50%" />
    <TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_toRightOf="@id/fifty_huntv"
        android:background="#ffff5566"
        android:text="80%-50%"
        app:layout_heightPercent="80%"
        app:layout_widthPercent="50%"
        />

</android.support.percent.PercentRelativeLayout>

หลีกเลี่ยงการลดประสิทธิภาพซ้อนกันLinearLayoutด้วยน้ำหนักยอดเยี่ยมจริง ๆ !!!


@ ด่านใช่เพราะเรามีเลย์เอาต์แบบเชิงเส้นซ้อนกันด้วยน้ำหนัก
nitesh

3
"คลาสนี้เลิกใช้แล้วในระดับ API 26.0.0-beta1 ลองใช้ ConstraintLayout และเค้าโครงที่เกี่ยวข้องแทน" developer.android.com/reference/android/support/percent/ …
saiyancoder

7
ฉันไม่ชอบข้อ จำกัด เค้าโครง มันไม่ได้หยั่งรู้ได้สำหรับฉัน
Carson Holzheimer

8
ข้อ จำกัด
เค้าโครง

1
บางทีคำอธิบายของแอปเปิ้ลที่มีต่อข้อ จำกัด การเปลี่ยนอัตโนมัติอาจชัดเจนกว่าและตรรกะก็เหมือนกันมันสามารถช่วยได้ น่าเสียดายที่ฉันพบข้อ จำกัด ของ droid ในการใช้งานหนัก / verbose มากกว่า iOS ของ AutoLayout
AdricoM

46

ฉันคิดว่า (และฉันอาจจะถูกตำหนิในเรื่องนี้) แต่อีกครั้งฉันคิดว่าโทรศัพท์ของฉันมีโปรเซสเซอร์ Quad-Core เพื่อแข่งขัน (ถ้าไม่ทำลายอย่างสิ้นเชิง) พีซีส่วนใหญ่ของคนในบ้าน

ฉันยังคิดว่าความสามารถด้านฮาร์ดแวร์ประเภทนี้เป็นอนาคตของโทรศัพท์

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

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

(โปรดทราบว่าฉันเป็นคนตลกเล็กน้อยและไม่ต้องจริงจังอะไรกับโพสต์นี้มากนักดังนั้นความคิดที่ว่ามีสิ่งอื่น ๆ ที่คุณควรปรับให้เหมาะสมก่อนและความกังวลเกี่ยวกับน้ำหนักลึก 2-3 ระดับไม่ช่วยอะไร สุขภาพของคุณ)


2
ที่ถ่ายและเห็นด้วยเป็นหลัก แต่เคยได้ยินว่า iPhone ใช้งานโดยเฉลี่ย (รวมถึงบริการ / เว็บไซต์ที่สนับสนุนการใช้งาน) ประมาณพลังงานต่อปีเท่ากับตู้เย็นในครัวเรือนของสหรัฐอเมริกาโดยเฉลี่ย ดังนั้นจึงเป็นความรับผิดชอบของเราในฐานะนักพัฒนาที่จะต้องคำนึงถึงผลกระทบต่อสิ่งแวดล้อมเช่นนี้ เห็นได้ชัดว่ามันเป็นการกระทำที่สมดุลเสมอ: เวลาต้นทุนประสิทธิภาพความมั่นคงและโดยทั่วไปฉันเห็นด้วยกับมุมมองของคุณ - แต่คิดว่าเราควรพิจารณาถึงผลกระทบเช่นนี้ด้วย เห็นได้ชัดว่าการบำรุงรักษา / การขยายมาที่นี่ด้วย อย่างไรก็ตาม - ชี้ไปที่และขอบคุณ
MemeDeveloper

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

11

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

ใน ICS (API ระดับ 14) มีการGridLayoutเพิ่มซึ่งช่วยให้การแก้ปัญหาที่เรียบง่ายและ 'แบน' สำหรับรูปแบบจำนวนมากซึ่งต้องมีน้ำหนักก่อนหน้านี้ หากคุณกำลังพัฒนาสำหรับ Android รุ่นก่อนหน้าคุณจะมีเวลาในการลบน้ำหนักเล็กน้อยยากขึ้น แต่การใช้ a RelativeLayoutและแบนให้มากที่สุดเท่าที่เป็นไปได้ของเค้าโครงของคุณในรถแท็กซี่นั้นมักจะกำจัดน้ำหนักที่ซ้อนกันมากมาย


9
ผมไม่คิดว่าคุณสามารถบรรลุผลเช่นเดียวกันกับหรือGridLayout RelativeLayoutเช่นสำหรับGridLayout: "GridLayout ไม่ได้ให้การสนับสนุนหลักการของน้ำหนักตามที่กำหนดไว้ในน้ำหนักโดยทั่วไปจึงไม่สามารถกำหนดค่า GridLayout เพื่อกระจายพื้นที่ส่วนเกินระหว่างองค์ประกอบหลายส่วน"
Timmmm

การเริ่มต้นใน API 21 มีการเพิ่มแนวคิดเรื่องน้ำหนักลงใน GridLayout เพื่อรองรับอุปกรณ์ Android รุ่นเก่าคุณสามารถใช้ GridLayout จากไลบรารีการสนับสนุน v7 android.support.v7.widget.GridLayout
Эвансгелист Evansgelist

2

มีวิธีแก้ปัญหาง่ายๆเพื่อหลีกเลี่ยง LinearLayouts ที่ซ้อนกันด้วยน้ำหนัก - เพียงใช้ Tablelayout กับ weighSum และ LinearLayout ที่ซ้อนกันกับ weightSum - Tablelayout มีคุณลักษณะเช่นเดียวกับ LinearLayout (การวางแนว weightSum, layout_weight ฯลฯ ) มีผลงานไม่ดี "

ตัวอย่าง:

 <TableLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:weightSum="1">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.8"/>


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.2"
            android:orientation="horizontal"
            android:weightSum="1">


            <ImageView
                android:layout_height="match_parent"
                android:layout_width="0dp"
                android:layout_weight="0.4"/>

            <TextView
                android:layout_height="match_parent"
                android:layout_width="0dp"
                android:layout_weight="0.6"/>


            </LinearLayout>

    </TableLayout>

1

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.