จัดการเหตุการณ์ชั้นข้อมูลใน Wear

เมื่อเรียกใช้ Data Layer API คุณจะได้รับสถานะของการเรียกใช้เมื่อการเรียกใช้เสร็จสมบูรณ์ นอกจากนี้ คุณยังฟังเหตุการณ์ข้อมูลที่เกิดจากการเปลี่ยนแปลงข้อมูลที่แอปของคุณทำได้ทุกที่ในเครือข่าย Wear OS by Google

ดูตัวอย่างการทำงานกับ Data Layer API อย่างมีประสิทธิภาพได้ที่แอป Android DataLayer Sample

รอสถานะของการเรียกใช้ Data Layer

การเรียกใช้ Data Layer API เช่น การเรียกใช้โดยใช้เมธอด putDataItem ของคลาส DataClient บางครั้งจะแสดงผลออบเจ็กต์ Task<ResultType> ทันทีที่สร้างออบเจ็กต์ Task ระบบจะจัดคิวการดำเนินการในเบื้องหลัง หากคุณไม่ดำเนินการใดๆ เพิ่มเติมหลังจากนี้ การดำเนินการจะเสร็จสมบูรณ์โดยไม่มีการแจ้งเตือน

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

การเรียกแบบอะซิงโครนัส

หากโค้ดทำงานในเทรด UI หลัก อย่าทำการเรียกที่บล็อกไปยัง Data Layer API และใช้โครูทีนเพื่อเรียก putDataItem

private suspend fun Context.sendDataAsync(count: Int) {
    try {
        val putDataReq: PutDataRequest = PutDataMapRequest.create("/count").run {
            dataMap.putInt("count_key", count)
            asPutDataRequest()
        }
        val dataItem = Wearable.getDataClient(this).putDataItem(putDataReq).await()
        handleDataItem(dataItem)
    } catch (e: Exception) {
        handleDataItemError(e)
    } finally {
        handleTaskComplete()
    }
}

private fun handleDataItem(dataItem: DataItem) { }
private fun handleDataItemError(exception: Exception) { }
private fun handleTaskComplete() { }

ดูความเป็นไปได้อื่นๆ ได้ที่ Task API ซึ่งรวมถึงการเชื่อมโยงการดำเนินการ ของงานต่างๆ

การโทรแบบซิงโครนัส

หากโค้ดทำงานในเทรดแฮนเดิลแยกต่างหากในบริการเบื้องหลัง เช่น ใน WearableListenerService ให้ใช้ runBlocking เพื่อทำการเรียกที่บล็อกไปยัง putDataItem

หมายเหตุ: อย่าเรียกใช้ฟังก์ชันนี้ในขณะที่อยู่ในเทรดหลัก

private fun Context.sendDataSync(count: Int) = runBlocking {
    val putDataReq = PutDataMapRequest.create("/count").run {
        dataMap.putInt("count_key", count)
        asPutDataRequest()
    }

    try {
        val result = Wearable.getDataClient(this@sendDataSync)
            .putDataItem(putDataReq)
            .await()
        // Logic for success
    } catch (e: Exception) {
        // Handle failure
    }
}

รอรับเหตุการณ์ชั้นข้อมูล

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

หากต้องการรอรับเหตุการณ์ชั้นข้อมูล คุณมี 2 ตัวเลือก ดังนี้

ทั้ง 2 ตัวเลือกนี้จะลบล้างวิธีการเรียกกลับของเหตุการณ์ข้อมูลสําหรับ เหตุการณ์ที่คุณสนใจจัดการ

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

ใช้ WearableListenerService

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

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

เหตุการณ์บางอย่างที่คุณสามารถฟังได้โดยใช้ WearableListenerService มีดังนี้

  • onDataChanged(): เมื่อใดก็ตามที่มีการสร้าง ลบ หรือ เปลี่ยนแปลงออบเจ็กต์รายการข้อมูล ระบบจะทริกเกอร์การเรียกกลับนี้ในโหนดที่เชื่อมต่อทั้งหมด
  • onMessageReceived(): ข้อความที่ส่งจากโหนดจะทริกเกอร์ การเรียกกลับนี้ในโหนดเป้าหมาย
  • onCapabilityChanged(): เมื่อความสามารถที่อินสแตนซ์ของแอปโฆษณาพร้อมใช้งานในเครือข่าย เหตุการณ์ดังกล่าวจะทริกเกอร์การเรียกกลับนี้ หากต้องการค้นหาโหนดที่อยู่ใกล้เคียง คุณสามารถค้นหาเมธอด isNearby()ของโหนดที่ระบุไว้ในการเรียกกลับ

นอกจากนี้ คุณยังฟังเหตุการณ์จาก ChannelClient.ChannelCallback ได้ด้วย เช่น onChannelOpened()

เหตุการณ์ก่อนหน้าทั้งหมดจะดำเนินการในเธรดเบื้องหลัง ไม่ใช่ในเธรดหลัก

หากต้องการสร้าง WearableListenerService ให้ทำตามขั้นตอนต่อไปนี้

  1. สร้างคลาสที่ขยาย WearableListenerService
  2. ฟังเหตุการณ์ที่คุณสนใจ เช่น onDataChanged()
  3. ประกาศตัวกรอง Intent ในไฟล์ Manifest ของ Android เพื่อแจ้งให้ระบบทราบเกี่ยวกับ WearableListenerService การประกาศนี้ช่วยให้ระบบเชื่อมโยงบริการของคุณได้ตามต้องการ

ตัวอย่างต่อไปนี้แสดงวิธีใช้ WearableListenerService

class DataLayerListenerService : WearableListenerService() {

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDataChanged: $dataEvents")
        }

        // Loop through the events and send a message
        // to the node that created the data item.
        dataEvents
            .map { it.dataItem.uri }
            .forEach { uri ->
                // Get the node ID from the host value of the URI.
                val nodeId: String = uri.host!!
                // Set the data of the message to be the bytes of the URI.
                val payload: ByteArray = uri.toString().toByteArray()

                // Send the RPC.
                Wearable.getMessageClient(this)
                    .sendMessage(
                        nodeId,
                        DATA_ITEM_RECEIVED_PATH,
                        payload
                    )
            }
    }
}

ส่วนต่อไปนี้จะอธิบายวิธีใช้ตัวกรอง Intent กับ Listener นี้

ใช้ตัวกรองกับ WearableListenerService

ตัวกรอง Intent สำหรับWearableListenerService ตัวอย่างที่แสดงในส่วนก่อนหน้า อาจมีลักษณะดังนี้

<service
    android:name=".snippets.datalayer.DataLayerListenerService"
    android:exported="true"
    tools:ignore="ExportedService" >
    <intent-filter>
        <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
        <data
            android:scheme="wear"
            android:host="*"
            android:path="/start-activity" />
    </intent-filter>
</service>

DATA_CHANGED ตัวกรองการดำเนินการจะบอกระบบว่าแอปของคุณสนใจเหตุการณ์ใน Data Layer

ในตัวอย่างนี้ นาฬิกาจะรอรับ/start-activityรายการข้อมูล และโทรศัพท์จะรอรับข้อความ /data-item-received (DATA_ITEM_RECEIVED_PATH) ตอบกลับ

ระบบจะใช้กฎการจับคู่ตัวกรอง Android มาตรฐาน คุณระบุบริการหลายรายการ ต่อไฟล์ Manifest, ตัวกรอง Intent หลายรายการต่อบริการ, การดำเนินการหลายรายการต่อตัวกรอง และกลุ่มข้อมูลหลายรายการต่อตัวกรองได้ ตัวกรองสามารถจับคู่กับโฮสต์ไวลด์การ์ดหรือโฮสต์ที่เฉพาะเจาะจง หากต้องการจับคู่ในโฮสต์ไวลด์การ์ด ให้ใช้ host="*" หากต้องการจับคู่ในโฮสต์ที่เฉพาะเจาะจง ให้ระบุ host=<node_id>

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับประเภทตัวกรองที่ Wear OS รองรับได้ที่เอกสารอ้างอิง API สำหรับ WearableListenerService

ดูข้อมูลเพิ่มเติมเกี่ยวกับตัวกรองข้อมูลและกฎการจับคู่ได้ในเอกสารอ้างอิง API สำหรับองค์ประกอบ Manifest ของ <data>

เมื่อจับคู่ตัวกรอง Intent โปรดคำนึงถึงกฎสำคัญ 2 ข้อต่อไปนี้

  • หากไม่ได้ระบุสคีมาสำหรับตัวกรอง Intent ระบบจะเพิกเฉยต่อแอตทริบิวต์ URI อื่นๆ ทั้งหมด
  • หากไม่ได้ระบุโฮสต์สำหรับตัวกรอง ระบบจะไม่สนใจแอตทริบิวต์เส้นทางทั้งหมด

ใช้ผู้ฟังสด

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

หากต้องการแนะนำแนวทางที่สะอาดและปลอดภัยยิ่งขึ้น ให้ใช้ Lifecycle Observer การใช้ Lifecycle Observer จะช่วยย้ายตรรกะการลงทะเบียนออกจาก onResume() ของ Activity ไปยังคลาสที่แยกต่างหากและนำกลับมาใช้ใหม่ได้ ซึ่งจะใช้ DefaultLifecycleObserver

แนวทางนี้จะช่วยให้กิจกรรมของคุณมีประสิทธิภาพและป้องกันข้อบกพร่องที่พบบ่อย เช่น การลืม ยกเลิกการลงทะเบียน Listener

1. สร้าง Listener ที่รับรู้ถึงวงจรขององค์ประกอบ

คลาสนี้จะรวม DataClient.OnDataChangedListener และจัดการการสมัครใช้บริการของตัวเองโดยอัตโนมัติ ตามวงจรของกิจกรรม

class WearDataLayerObserver(
    private val dataClient: DataClient,
    private val onDataReceived: (DataEventBuffer) -> Unit
) : DefaultLifecycleObserver, DataClient.OnDataChangedListener {

    // Implementation of the DataClient listener
    override fun onDataChanged(dataEvents: DataEventBuffer) {
        onDataReceived(dataEvents)
    }

    // Automatically register when the Activity starts
    override fun onResume(owner: LifecycleOwner) {
        dataClient.addListener(this)
    }

    // Automatically unregister when the Activity pauses
    override fun onPause(owner: LifecycleOwner) {
        dataClient.removeListener(this)
    }
}

2. การใช้งานในกิจกรรมของคุณ

ตอนนี้กิจกรรมของคุณไม่จำเป็นต้องลบล้าง onResume() หรือ onPause() สำหรับ Wear API คุณเพิ่มผู้สังเกตการณ์ได้ครั้งเดียวใน onCreate()

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

        val dataClient = Wearable.getDataClient(this)

        // Create the observer and link it to the activity's lifecycle
        val wearObserver = WearDataLayerObserver(dataClient) { dataEvents ->
            handleDataEvents(dataEvents)
        }

        lifecycle.addObserver(wearObserver)
    }

    private fun handleDataEvents(dataEvents: DataEventBuffer) {
        // ... filter and process events ...
    }
}

ทำไมพรอมต์นี้จึงดีขึ้น

  • กิจกรรม Cleaner: คุณนำโค้ดสำเร็จรูปออกจากเมธอดวงจรของกิจกรรม
  • ความปลอดภัย: DefaultLifecycleObserver ช่วยยืนยันว่าระบบได้นำ Listener ออกแล้ว แม้ว่า Activity จะถูกทำลายโดยไม่คาดคิด ซึ่งจะช่วยป้องกันไม่ให้เกิดการรั่วไหลของหน่วยความจำ
  • การนำกลับมาใช้ใหม่: คุณสามารถเสียบ WearDataLayerObserver นี้เข้ากับ Activity หรือ Fragment ใดก็ได้โดยไม่ต้องเขียนตรรกะการลงทะเบียนใหม่
  • การแยกส่วน: แยกตรรกะของเวลาที่ต้องฟังออกจากตรรกะของ สิ่งที่ต้องทำกับข้อมูล

ใช้ตัวกรองกับผู้ฟังแบบเรียลไทม์

ดังที่ได้กล่าวไว้ก่อนหน้านี้ คุณสามารถระบุตัวกรอง Intent สำหรับออบเจ็กต์ WearableListenerServiceที่อิงตามไฟล์ Manifest ได้เช่นเดียวกับที่ใช้ตัวกรอง Intent เมื่อลงทะเบียน Listener แบบสดผ่าน Wearable API กฎเดียวกันนี้ มีผลกับทั้งผู้ฟังที่ใช้ API และผู้ฟังที่ใช้ไฟล์ Manifest

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