การจัดการวงจรด้วยคอมโพเนนต์ที่รับรู้วงจร   เป็นส่วนหนึ่งของ Android Jetpack

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

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

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

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

สมมติว่าเรามีกิจกรรมที่แสดงตำแหน่งของอุปกรณ์บนหน้าจอ การใช้งานที่พบบ่อยอาจมีลักษณะดังนี้

Kotlin

internal class MyLocationListener(
        private val context: Context,
        private val callback: (Location) -> Unit
) {

    fun start() {
        // connect to system location service
    }

    fun stop() {
        // disconnect from system location service
    }
}

class MyActivity : AppCompatActivity() {
    private lateinit var myLocationListener: MyLocationListener

    override fun onCreate(...) {
        myLocationListener = MyLocationListener(this) { location ->
            // update UI
        }
    }

    public override fun onStart() {
        super.onStart()
        myLocationListener.start()
        // manage other components that need to respond
        // to the activity lifecycle
    }

    public override fun onStop() {
        super.onStop()
        myLocationListener.stop()
        // manage other components that need to respond
        // to the activity lifecycle
    }
}

Java

class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) {
        // ...
    }

    void start() {
        // connect to system location service
    }

    void stop() {
        // disconnect from system location service
    }
}

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    @Override
    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, (location) -> {
            // update UI
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        myLocationListener.start();
        // manage other components that need to respond
        // to the activity lifecycle
    }

    @Override
    public void onStop() {
        super.onStop();
        myLocationListener.stop();
        // manage other components that need to respond
        // to the activity lifecycle
    }
}

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

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

Kotlin

class MyActivity : AppCompatActivity() {
    private lateinit var myLocationListener: MyLocationListener

    override fun onCreate(...) {
        myLocationListener = MyLocationListener(this) { location ->
            // update UI
        }
    }

    public override fun onStart() {
        super.onStart()
        Util.checkUserStatus { result ->
            // what if this callback is invoked AFTER activity is stopped?
            if (result) {
                myLocationListener.start()
            }
        }
    }

    public override fun onStop() {
        super.onStop()
        myLocationListener.stop()
    }

}

Java

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, location -> {
            // update UI
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        Util.checkUserStatus(result -> {
            // what if this callback is invoked AFTER activity is stopped?
            if (result) {
                myLocationListener.start();
            }
        });
    }

    @Override
    public void onStop() {
        super.onStop();
        myLocationListener.stop();
    }
}

แพ็กเกจ androidx.lifecycle มีคลาสและอินเทอร์เฟซที่ช่วยให้คุณจัดการปัญหาเหล่านี้ได้อย่างยืดหยุ่นและแยกส่วน

วงจร

Lifecycle เป็นคลาสที่มีข้อมูลเกี่ยวกับสถานะวงจรชีวิตของคอมโพเนนต์ (เช่น กิจกรรมหรือฟragment) และอนุญาตให้ออบเจ็กต์อื่นๆ สังเกตสถานะนี้ได้

Lifecycle ใช้การแจกแจงหลัก 2 รายการเพื่อติดตามสถานะวงจรของลูกค้าสําหรับคอมโพเนนต์ที่เกี่ยวข้อง ดังนี้

กิจกรรม
เหตุการณ์ในวงจรที่ส่งมาจากเฟรมเวิร์กและคลาส Lifecycle เหตุการณ์เหล่านี้จะแมปกับเหตุการณ์ Callback ในกิจกรรมและข้อมูลโค้ด
รัฐ
สถานะปัจจุบันของคอมโพเนนต์ที่ออบเจ็กต์ Lifecycle ติดตาม
แผนภาพสถานะวงจร
รูปที่ 1 สถานะและเหตุการณ์ที่ประกอบขึ้นเป็นวงจรของกิจกรรม Android

ให้คิดว่าสถานะเป็นโหนดของกราฟ และเหตุการณ์เป็นขอบระหว่างโหนดเหล่านี้

คลาสสามารถตรวจสอบสถานะวงจรชีวิตของคอมโพเนนต์ได้โดยการใช้ DefaultLifecycleObserver และลบล้างเมธอดที่เกี่ยวข้อง เช่น onCreate, onStart เป็นต้น จากนั้นคุณสามารถเพิ่มผู้สังเกตการณ์ได้โดยเรียกใช้เมธอด addObserver() ของคลาส Lifecycle และส่งอินสแตนซ์ของผู้สังเกตการณ์ ดังที่แสดงในตัวอย่างต่อไปนี้

Kotlin

class MyObserver : DefaultLifecycleObserver {
    override fun onResume(owner: LifecycleOwner) {
        connect()
    }

    override fun onPause(owner: LifecycleOwner) {
        disconnect()
    }
}

myLifecycleOwner.getLifecycle().addObserver(MyObserver())

Java

public class MyObserver implements DefaultLifecycleObserver {
    @Override
    public void onResume(LifecycleOwner owner) {
        connect()
    }

    @Override
    public void onPause(LifecycleOwner owner) {
        disconnect()
    }
}

myLifecycleOwner.getLifecycle().addObserver(new MyObserver());

ในตัวอย่างข้างต้น ออบเจ็กต์ myLifecycleOwner ใช้อินเทอร์เฟซ LifecycleOwner ซึ่งอธิบายไว้ในส่วนถัดไป

LifecycleOwner

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

อินเทอร์เฟซนี้จะแยกการเป็นเจ้าของ Lifecycle ออกจากคลาสแต่ละคลาส เช่น Fragment และ AppCompatActivity และอนุญาตให้เขียนคอมโพเนนต์ที่ทำงานร่วมกับคลาสเหล่านั้นได้ คลาสแอปพลิเคชันที่กำหนดเองใดๆ สามารถใช้อินเทอร์เฟซ LifecycleOwner ได้

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

สําหรับตัวอย่างการติดตามตําแหน่ง เราสามารถสร้างคลาส MyLocationListener ให้ใช้งาน DefaultLifecycleObserver แล้วเริ่มต้นด้วย Lifecycle ของกิจกรรมในเมธอด onCreate() วิธีนี้ช่วยให้คลาส MyLocationListener ทำงานได้ด้วยตัวเอง ซึ่งหมายความว่าจะมีการประกาศตรรกะในการตอบสนองต่อการเปลี่ยนแปลงสถานะวงจรใน MyLocationListener แทนกิจกรรม การที่คอมโพเนนต์แต่ละรายการจัดเก็บตรรกะของตนเองจะช่วยให้จัดการตรรกะของกิจกรรมและข้อมูลโค้ดได้ง่ายขึ้น

Kotlin

class MyActivity : AppCompatActivity() {
    private lateinit var myLocationListener: MyLocationListener

    override fun onCreate(...) {
        myLocationListener = MyLocationListener(this, lifecycle) { location ->
            // update UI
        }
        Util.checkUserStatus { result ->
            if (result) {
                myLocationListener.enable()
            }
        }
    }
}

Java

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
            // update UI
        });
        Util.checkUserStatus(result -> {
            if (result) {
                myLocationListener.enable();
            }
        });
  }
}

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

คลาส Lifecycle ช่วยให้ออบเจ็กต์อื่นๆ ค้นหาสถานะปัจจุบันได้ เพื่อให้ Use Case นี้ง่ายขึ้น

Kotlin

internal class MyLocationListener(
        private val context: Context,
        private val lifecycle: Lifecycle,
        private val callback: (Location) -> Unit
): DefaultLifecycleObserver {

    private var enabled = false

    override fun onStart(owner: LifecycleOwner) {
        if (enabled) {
            // connect
        }
    }

    fun enable() {
        enabled = true
        if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
            // connect if not connected
        }
    }

    override fun onStop(owner: LifecycleOwner) {
        // disconnect if connected
    }
}

Java

class MyLocationListener implements DefaultLifecycleObserver {
    private boolean enabled = false;
    public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {
       ...
    }

    @Override
    public void onStart(LifecycleOwner owner) {
        if (enabled) {
           // connect
        }
    }

    public void enable() {
        enabled = true;
        if (lifecycle.getCurrentState().isAtLeast(STARTED)) {
            // connect if not connected
        }
    }

    @Override
    public void onStop(LifecycleOwner owner) {
        // disconnect if connected
    }
}

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

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

การใช้ LifecycleOwner ที่กําหนดเอง

ส่วนต่างๆ และกิจกรรมใน Support Library 26.1.0 ขึ้นไปใช้LifecycleOwner อินเตอร์เฟซอยู่แล้ว

หากมีคลาสที่กำหนดเองที่ต้องการสร้าง LifecycleOwner คุณสามารถใช้คลาส LifecycleRegistry แต่ต้องส่งต่อเหตุการณ์ไปยังคลาสนั้น ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้

Kotlin

class MyActivity : Activity(), LifecycleOwner {

    private lateinit var lifecycleRegistry: LifecycleRegistry

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        lifecycleRegistry = LifecycleRegistry(this)
        lifecycleRegistry.markState(Lifecycle.State.CREATED)
    }

    public override fun onStart() {
        super.onStart()
        lifecycleRegistry.markState(Lifecycle.State.STARTED)
    }

    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }
}

Java

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry lifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lifecycleRegistry = new LifecycleRegistry(this);
        lifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        lifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return lifecycleRegistry;
    }
}

แนวทางปฏิบัติแนะนำสำหรับคอมโพเนนต์ที่รับรู้วงจรของลูกค้า

  • ควบคุม UI (กิจกรรมและส่วนต่างๆ) ให้น้อยที่สุดเท่าที่เป็นไปได้ โดยไม่ควรพยายามรวบรวมข้อมูลของตนเอง แต่ให้ใช้ ViewModel แทน และสังเกตออบเจ็กต์ LiveData เพื่อแสดงการเปลี่ยนแปลงในมุมมอง
  • ลองเขียน UI ที่ขับเคลื่อนโดยข้อมูลโดยที่ความรับผิดชอบของเครื่องมือควบคุม UI คือการอัปเดตมุมมองเมื่อข้อมูลมีการเปลี่ยนแปลง หรือแจ้งการดําเนินการของผู้ใช้กลับไปยัง ViewModel
  • ใส่ตรรกะข้อมูลในคลาส ViewModel ViewModel ควรทำหน้าที่เป็นเครื่องมือเชื่อมต่อระหว่างตัวควบคุม UI กับส่วนที่เหลือของแอป แต่โปรดทราบว่า ViewModel ไม่ได้มีหน้าที่ดึงข้อมูล (เช่น จากเครือข่าย) แต่ViewModel ควรเรียกใช้คอมโพเนนต์ที่เหมาะสมเพื่อดึงข้อมูล แล้วส่งผลลัพธ์กลับไปยังตัวควบคุม UI
  • ใช้การเชื่อมโยงข้อมูลเพื่อรักษาอินเทอร์เฟซที่เรียบร้อยระหว่างมุมมองกับตัวควบคุม UI ซึ่งช่วยให้คุณทำให้มุมมองเป็นแบบประกาศมากขึ้นและลดโค้ดการอัปเดตที่ต้องเขียนในกิจกรรมและข้อมูลโค้ดได้ หากต้องการดำเนินการนี้ในภาษาโปรแกรม Java ให้ใช้ไลบรารีอย่าง Butter Knife เพื่อหลีกเลี่ยงโค้ดที่ซ้ำกันและมีการสร้างแบบนามธรรมที่ดียิ่งขึ้น
  • หาก UI มีความซับซ้อน ให้พิจารณาสร้างคลาส presenter เพื่อจัดการการแก้ไข UI งานนี้อาจทําได้ยาก แต่จะช่วยให้ทดสอบคอมโพเนนต์ UI ได้ง่ายขึ้น
  • หลีกเลี่ยงการอ้างอิงบริบท View หรือ Activity ใน ViewModel หาก ViewModel มีอายุมากกว่ากิจกรรม (ในกรณีที่มีการเปลี่ยนแปลงการกําหนดค่า) กิจกรรมจะรั่วไหลและระบบเก็บขยะจะไม่จัดการอย่างถูกต้อง
  • ใช้ Kotlin coroutine เพื่อจัดการงานที่ทำงานต่อเนื่องเป็นเวลานานและการดำเนินการอื่นๆ ที่ทำงานแบบไม่พร้อมกันได้

Use Case สําหรับคอมโพเนนต์ที่ทราบวงจร

คอมโพเนนต์ที่รับรู้วงจรช่วยให้คุณจัดการวงจรได้ง่ายขึ้นอย่างมากในหลายกรณี ตัวอย่างบางส่วนมีดังนี้

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

การจัดการเหตุการณ์หยุด

เมื่อ Lifecycle เป็นของ AppCompatActivity หรือ Fragment สถานะของ Lifecycle จะเปลี่ยนเป็น CREATED และระบบจะส่งเหตุการณ์ ON_STOP เมื่อมีการเรียก onSaveInstanceState() ของ AppCompatActivity หรือ Fragment

เมื่อบันทึกสถานะของ Fragment หรือ AppCompatActivity ผ่าน onSaveInstanceState() ระบบจะถือว่า UI ของ Fragment หรือ AppCompatActivity นั้นเปลี่ยนแปลงไม่ได้จนกว่าจะเรียกใช้ ON_START การพยายามแก้ไข UI หลังจากบันทึกสถานะมีแนวโน้มที่จะทําให้สถานะการนําทางของแอปพลิเคชันไม่สอดคล้องกัน ด้วยเหตุนี้ FragmentManager จึงแสดงข้อยกเว้นหากแอปเรียกใช้ FragmentTransaction หลังจากบันทึกสถานะ ดูรายละเอียดได้ที่ commit()

LiveData ป้องกันกรณีขอบเขตนี้ตั้งแต่เริ่มต้นโดยงดเรียกใช้ผู้สังเกตการณ์หาก Lifecycle ที่เชื่อมโยงของผู้สังเกตการณ์มีค่าไม่น้อยกว่า STARTED เบื้องหลังคือมีการเรียกใช้ isAtLeast() ก่อนตัดสินใจเรียกใช้ผู้สังเกตการณ์

ขออภัย วิธีการ onStop() ของ AppCompatActivity เรียกว่า after onSaveInstanceState() ซึ่งทำให้เกิดช่องว่างที่ไม่อนุญาตให้มีการเปลี่ยนแปลงสถานะของ UI แต่ Lifecycle ยังไม่ได้ย้ายไปยังสถานะ CREATED

เพื่อป้องกันปัญหานี้ คลาส Lifecycle ในเวอร์ชัน beta2 และต่ำกว่าจะทําเครื่องหมายสถานะเป็น CREATED โดยไม่มีการส่งเหตุการณ์เพื่อให้โค้ดที่ตรวจสอบสถานะปัจจุบันได้รับค่าจริง แม้ว่าระบบจะไม่ส่งเหตุการณ์จนกว่าจะมีการเรียกใช้ onStop()

แต่วิธีนี้มีปัญหาสำคัญ 2 ข้อ ได้แก่

  • ใน API ระดับ 23 และต่ำกว่า ระบบ Android จะบันทึกสถานะของกิจกรรมแม้ว่ากิจกรรมนั้นจะถูกครอบคลุมบางส่วนโดยกิจกรรมอื่นก็ตาม กล่าวคือ ระบบ Android จะเรียก onSaveInstanceState() แต่ไม่จำเป็นต้องเรียก onStop() ซึ่งอาจทำให้เกิดช่วงเวลาที่นานที่ผู้สังเกตการณ์ยังคงคิดว่าวงจรยังมีการใช้งานอยู่ แม้ว่าจะไม่สามารถแก้ไขสถานะ UI ของวงจรได้ก็ตาม
  • คลาสที่ต้องการแสดงลักษณะการทำงานที่คล้ายกับคลาส LiveData ต้องใช้วิธีแก้ปัญหาที่ระบุโดย Lifecycle เวอร์ชัน beta 2 และต่ำกว่า

แหล่งข้อมูลเพิ่มเติม

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

ตัวอย่าง

  • Sunflower เป็นแอปสาธิตที่แสดงแนวทางปฏิบัติแนะนำเกี่ยวกับคอมโพเนนต์สถาปัตยกรรม

Codelabs

บล็อก