Pembangunan Aplikasi Mudah Alih Flutter · Pelajaran

Tiga Pepohon: Widget, Elemen dan RenderObject

Fahami cara Flutter menyelaraskan pepohon widget, elemen dan paparan semasa bina semula.

Pelajaran 1 daripada 413 langkah

Tiga Pepohon: Widget, Elemen dan RenderObject ialah pelajaran Pembangunan Aplikasi Mudah Alih Flutter percuma di CoddyKit. Ini ialah pelajaran 1 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Pembangunan Aplikasi Mudah Alih Flutter, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Pembangunan Aplikasi Mudah Alih Flutter merangkumi sejumlah 4 pelajaran.

Mengapa Tiga Pepohon?

Apabila anda menulis UI Flutter, anda menerangkan widget. Namun, rangka kerja sebenarnya mengekalkan tiga pepohon selari yang bekerjasama pada setiap bingkai:

  • Pepohon widget — objek konfigurasi tidak berubah yang anda bina dalam build().
  • Pepohon elemen — jambatan boleh ubah yang berjangka panjang, yang menyimpan keadaan dan menjejaki kedudukan dalam pepohon.
  • Pepohon RenderObject — objek yang sebenarnya melakukan reka letak, lukisan dan pengesanan sentuhan.

Memahami pemisahan ini ialah kunci untuk memahami kos bina semula, sebab widget const murah, dan sebab Key yang diletakkan pada tempat yang salah boleh merosakkan keadaan.

Widget Ialah Rangka Tindakan Tidak Berubah

Widget hanyalah penerangan ringan dan tidak berubah tentang sebahagian UI. Ia tidak menyimpan keadaan yang boleh berubah dan murah untuk dicipta serta dibuang. Memanggil build() membuang objek widget lama dan menghasilkan objek baharu setiap kali.

Oleh sebab widget boleh dibuang, membandingkan dua widget adalah pantas. Flutter menggunakan perbandingan itu untuk menentukan sama ada elemen dan objek pemapar yang lebih berat boleh digunakan semula dan bukannya dibina semula.

class Greeting extends StatelessWidget {
  const Greeting({super.key, required this.name});

  final String name;

  @override
  Widget build(BuildContext context) {
    // A brand-new Text widget is created on every rebuild.
    return Text('Hello, $name');
  }
}

Elemen Ialah Pepohon yang Hidup

Element dicipta oleh widget melalui createElement(). Tidak seperti widget, elemen boleh berubah dan berjangka panjang. Pepohon elemen ialah struktur masa jalan sebenar yang dilalui Flutter pada setiap bingkai.

Setiap elemen menyimpan rujukan kepada widget semasanya. Apabila binaan semula berlaku, elemen menerima widget baharu dan menentukan sama ada mahu mengekalkan dirinya (mengemas kini pada tempatnya) atau digantikan. Di sinilah penyelarasan berlaku.

  • StatelessElement — menyokong StatelessWidget.
  • StatefulElement — memiliki objek State, sebab itulah keadaan kekal merentas binaan semula.

Keadaan Hidup dalam Elemen, Bukan Widget

Inilah inti sebab reka bentuk Flutter berfungsi. Objek State dipegang oleh StatefulElement, yang kekal merentas binaan semula. StatefulWidget itu sendiri digantikan setiap kali ibu bapa dibina semula — tetapi elemen (dan keadaannya) kekal.

Itulah sebab pembilang anda tidak ditetapkan semula apabila ibu bapa dibina semula: widget itu baharu, tetapi elemen dan Statenya ialah tika yang sama.

class Counter extends StatefulWidget {
  const Counter({super.key});

  @override
  State<Counter> createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int _count = 0; // Survives parent rebuilds because the element persists.

  void _increment() => setState(() => _count++);

  @override
  Widget build(BuildContext context) {
    return TextButton(
      onPressed: _increment,
      child: Text('Count: $_count'),
    );
  }
}

RenderObjects Melakukan Kerja Berat

Bukan setiap widget mencipta objek render. Hanya RenderObjectWidgets (seperti Padding, Opacity, dan bahagian dalaman Text) menghasilkan entri dalam pepohon render. Widget komposisi seperti StatelessWidget dan StatefulWidget hanya menyelaraskan widget lain — widget ini tidak mempunyai objek render.

RenderObjects melaksanakan performLayout(), paint() dan pengujian sentuhan. Objek ini paling mahal untuk diproses, jadi Flutter berusaha sedaya upaya untuk mengemas kininya di tempat yang sama dan bukannya menciptanya semula.

  • Pepohon widget: dalam (banyak widget komposisi).
  • Pepohon elemen: kedalaman yang sama (satu elemen bagi setiap widget).
  • Pepohon render: lebih cetek (hanya widget objek render yang muncul).

Penyelarasan: updateChild

Algoritma penyelarasan berada dalam Element.updateChild(oldElement, newWidget). Bagi setiap kedudukan anak, Flutter menentukan satu daripada empat hasil berdasarkan widget baharu dan elemen lama:

  • Kemas kini di tempat yang sama — jika widget tersebut boleh dipadankan, elemen dan objek render digunakan semula.
  • Gantikan — jika widget tersebut tidak boleh dipadankan, nyahaktifkan subpepohon lama dan bina satu yang baharu.
  • Sisipkan — widget baharu tanpa elemen lama.
  • Buang — elemen lama tanpa widget baharu.

Laluan murah (kemas kini di tempat yang sama) inilah yang menjadikan Flutter pantas.

Peraturan Padanan: canUpdate

Sama ada sesuatu elemen boleh digunakan semula ditentukan oleh kaedah statik Widget.canUpdate(oldWidget, newWidget). Peraturannya mudah tetapi penting:

Dua widget sepadan jika dan hanya jika runtimeType dan key kedua-duanya sama.

Jika sepadan, elemen sedia ada mengekalkan kedudukan dan objek rendernya, kemudian hanya menggantikan konfigurasinya dengan widget baharu. Jika tidak sepadan, elemen lama dibuang dan subpepohon baharu dibina — termasuk kehilangan mana-mana State yang berkaitan.

// This is the actual decision rule used during reconciliation.
bool canUpdate(Object oldType, Object? oldKey, Object newType, Object? newKey) {
  return oldType == newType && oldKey == newKey;
}

void main() {
  // Same type, same (null) key -> reuse element.
  print(canUpdate('Text', null, 'Text', null)); // true
  // Different type -> rebuild subtree, state is lost.
  print(canUpdate('Text', null, 'Container', null)); // false
  // Same type, different keys -> NOT a match.
  print(canUpdate('Text', 'a', 'Text', 'b')); // false
}

Sebab Widget const Melangkau Binaan Semula

Apabila anda menandakan widget sebagai const, tika kanonik yang sama digunakan semula merentas binaan. Semasa penyelarasan, updateChild mendapati bahawa identical(oldWidget, newWidget) adalah benar dan boleh memintas seluruh subpepohon — tiada kemas kini elemen dan tiada kerja objek render.

Inilah sebab menambahkan const pada widget daun merupakan salah satu peningkatan prestasi yang paling murah: rujukan widget yang sama membolehkan Flutter memangkas seluruh cabang daripada penyelarasan.

class Header extends StatelessWidget {
  const Header({super.key});

  @override
  Widget build(BuildContext context) {
    // The const child is identical across rebuilds, so its element
    // subtree is skipped entirely during reconciliation.
    return const Padding(
      padding: EdgeInsets.all(16),
      child: Text('Settings'),
    );
  }
}

Kunci Membezakan Adik-Beradik daripada Jenis yang Sama

Apabila senarai mengandungi beberapa adik-beradik daripada jenis yang sama, Flutter secara lalai memadankan mereka berdasarkan kedudukan. Jika anda menyusun semula mereka, elemen (dan keadaannya) kekal terikat pada kedudukan lama — punca pepijat yang lazim dalam senarai berkeadaan.

Key mengubah identiti padanan. Dengan kunci, penyelarasan memadankan berdasarkan (runtimeType, key), bukannya kedudukan, jadi elemen dan Statenya mengikuti widget ke slot baharunya. Gunakan ValueKey untuk identiti data yang stabil.

class ReorderableTiles extends StatelessWidget {
  const ReorderableTiles({super.key, required this.items});

  final List<String> items;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        for (final id in items)
          // ValueKey lets each element's State follow its data on reorder.
          TodoTile(key: ValueKey(id), id: id),
      ],
    );
  }
}

GlobalKey: Memindahkan Elemen Merentas Pepohon

LocalKey (seperti ValueKey) hanya membezakan adik-beradik di bawah induk yang sama. GlobalKey adalah unik merentas seluruh aplikasi dan membolehkan elemen — dengan objek render serta keadaannya yang kekal utuh — dipindahkan ke induk yang sama sekali berbeza tanpa dibina semula.

GlobalKeys sangat berkuasa tetapi mahal: kunci ini memaksa rangka kerja menjejaki elemen secara global dan mencetuskan proses penyahaktifan/pengaktifan semula. Gunakannya dengan sengaja (contohnya, untuk mengekalkan pemain video semasa induknya berubah), bukan sebagai pilihan lalai.

Membuat Profil Tiga Pepohon

Dalam amalan, anda memerhati pepohon ini melalui DevTools dan penanda binaan semula:

  • Pemeriksa Flutter memaparkan pepohon widget; tukar paparannya untuk melihat pepohon render bersama saiz dan kekangan.
  • Statistik Binaan Semula / RepaintRainbow mendedahkan subpepohon yang menjalankan semula build() atau melukis semula.
  • Membungkus dengan RepaintBoundary mengasingkan subpepohon objek render ke dalam lapisannya sendiri supaya lukisan semulanya tidak merebak.

Model mentalnya: terlalu banyak widget dibina semula bermakna kos penyelarasan; terlalu banyak objek render melukis semula bermakna kos raster. Kedua-duanya ialah masalah yang berbeza dan memerlukan pembaikan yang berbeza.

class IsolatedChart extends StatelessWidget {
  const IsolatedChart({super.key, required this.painter});

  final CustomPainter painter;

  @override
  Widget build(BuildContext context) {
    // RepaintBoundary gives this CustomPaint its own render layer,
    // so frequent repaints here don't dirty the parent's layer.
    return RepaintBoundary(
      child: CustomPaint(painter: painter),
    );
  }
}

Semakan Pantas: Hasil Penyelarasan

StatefulWidget daripada jenis EditorPane tanpa kunci berada pada kedudukan 0 dalam Column. Dalam binaan semula seterusnya, induk mengembalikan PreviewPane (jenis yang berbeza) pada kedudukan 0. Apakah yang berlaku kepada elemen dan State milik EditorPane asal?

Imbas Kembali: Tiga Pepohon

Kini anda mempunyai model yang boleh digunakan tentang cara Flutter menyelaraskan UI:

  • Widget ialah pelan tindakan tidak berubah yang boleh dibuang — murah untuk dicipta semula pada setiap binaan.
  • Elemen ialah pepohon boleh ubah yang berumur panjang, yang menyimpan State dan menjalankan penyelarasan melalui updateChild.
  • RenderObjects ialah objek atur letak/lukisan yang mahal dan cuba dikemas kini oleh Flutter di tempat yang sama.
  • Penggunaan semula ditentukan oleh canUpdate: runtimeType dan key yang sama bermakna kemas kini di tempat yang sama; jika tidak, subpepohon (serta keadaannya) dibina semula.
  • Identiti const memintas penyelarasan; Keys mengawal identiti adik-beradik; GlobalKeys memindahkan elemen merentas pepohon; RepaintBoundary mengasingkan kos lukisan semula.

Dengan model mental ini, kerja prestasi menjadi tepat: kurangkan binaan semula yang tidak diperlukan (kos penyelarasan) dan lukisan semula yang tidak diperlukan (kos raster) secara berasingan.

Percuma untuk bermula

Pelajari Dart dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
22
Pelajaran
88

Soalan Lazim

Adakah pelajaran “Tiga Pepohon: Widget, Elemen dan RenderObject” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Pembangunan Aplikasi Mudah Alih Flutter, termasuk “Tiga Pepohon: Widget, Elemen dan RenderObject”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Pembangunan Aplikasi Mudah Alih Flutter merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Tiga Pepohon: Widget, Elemen dan RenderObject”?

Fahami cara Flutter menyelaraskan pepohon widget, elemen dan paparan semasa bina semula. Anda berlatih Pembangunan Aplikasi Mudah Alih Flutter menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Pembangunan Aplikasi Mudah Alih Flutter?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Pembangunan Aplikasi Mudah Alih Flutter di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 1 daripada 4.

Berapa lamakah pelajaran “Tiga Pepohon: Widget, Elemen dan RenderObject” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Pembangunan Aplikasi Mudah Alih Flutter ini?

Ya. Setiap pelajaran Pembangunan Aplikasi Mudah Alih Flutter menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Tiga Pepohon: Widget, Elemen dan RenderObject
  2. Menganalisis Kelewatan dengan Garis Masa DevTools
  3. RepaintBoundary, Widget Const dan Pemangkasan Bina Semula
  4. Pemanasan Awal Pencelup dan Pemindahan Impeller
← Kembali ke Pembangunan Aplikasi Mudah Alih Flutter