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

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

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

รอสถานะการเรียกใช้ชั้นข้อมูล

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

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

การโทรไม่พร้อมกัน

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

Kotlin

// Using Kotlin function references
task.addOnSuccessListener(::handleDataItem)
task.addOnFailureListener(::handleDataItemError)
task.addOnCompleteListener(::handleTaskComplete)
...
fun handleDataItem(dataItem: DataItem) { ... }
fun handleDataItemError(exception: Exception) { ... }
fun handleTaskComplete(task: Task<DataItem>) { ... }

Java

// Using Java 8 Lambdas.
task.addOnSuccessListener(dataItem -> handleDataItem(dataItem));
task.addOnFailureListener(exception -> handleDataItemError(exception));
task.addOnCompleteListener(task -> handleTaskComplete(task));

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

การโทรพร้อมกัน

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

หมายเหตุ: โปรดอย่าเรียกใช้ส่วนนี้ขณะอยู่ในเทรดหลัก

Kotlin

try {
    Tasks.await(dataItemTask).apply {
        Log.d(TAG, "Data item set: $uri")
    }
}
catch (e: ExecutionException) { ... }
catch (e: InterruptedException) { ... }

Java

try {
    DataItem item = Tasks.await(dataItemTask);
    Log.d(TAG, "Data item set: " + item.getUri());
} catch (ExecutionException | InterruptedException e) {
  ...
}

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

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

คุณมี 2 ตัวเลือกในการวิเคราะห์เหตุการณ์ชั้นข้อมูล

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

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

ใช้ WearableListenerService

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

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

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

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

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

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

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

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

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

Kotlin

private const val TAG = "DataLayerSample"
private const val START_ACTIVITY_PATH = "/start-activity"
private const val DATA_ITEM_RECEIVED_PATH = "/data-item-received"

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)
                }
    }
}

Java

public class DataLayerListenerService extends WearableListenerService {
    private static final String TAG = "DataLayerSample";
    private static final String START_ACTIVITY_PATH = "/start-activity";
    private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received";

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        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.
        for (DataEvent event : dataEvents) {
            Uri uri = event.getDataItem().getUri();

            // Get the node ID from the host value of the URI.
            String nodeId = uri.getHost();
            // Set the data of the message to be the bytes of the URI.
            byte[] payload = uri.toString().getBytes();

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

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

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

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

<service android:name=".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 จะแทนที่ ก่อนหน้านี้ได้แนะนำการดำเนินการ BIND_LISTENER เพื่อให้มีเฉพาะ เหตุการณ์ต่างๆ ปลุกหรือเปิดแอปของคุณ การเปลี่ยนแปลงนี้จะช่วยปรับปรุงประสิทธิภาพของระบบ และลดการใช้แบตเตอรี่และค่าใช้จ่ายอื่นๆ ที่เกี่ยวข้องกับ แอป ในตัวอย่างนี้ นาฬิกาจะคอยตรวจจับ รายการข้อมูล /start-activity และ โทรศัพท์จะคอยฟังการตอบกลับข้อความ /data-item-received

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

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

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

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

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

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

ใช้การฟังแบบสด

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

หากต้องการสร้างกิจกรรมที่รอรับเหตุการณ์ข้อมูล ให้ทำตามขั้นตอนต่อไปนี้

  1. ใช้อินเทอร์เฟซที่ต้องการ
  2. ในเมธอด onCreate() หรือ onResume() ให้เรียกใช้ Wearable.getDataClient(this).addListener(), MessageClient.addListener(), CapabilityClient.addListener() หรือ ChannelClient.registerChannelCallback() เพื่อแจ้ง Google Play บริการที่กิจกรรมของคุณสนใจที่จะฟังเหตุการณ์ชั้นข้อมูล
  3. ใน onStop() หรือ onPause() ยกเลิกการลงทะเบียน Listener ทั้งหมดด้วย DataClient.removeListener(), MessageClient.removeListener(), CapabilityClient.removeListener() หรือ ChannelClient.unregisterChannelCallback()
  4. หากกิจกรรมสนใจเฉพาะเหตุการณ์ที่มีคำนำหน้าเส้นทางที่เจาะจง คุณจะเห็น สามารถเพิ่ม Listener ที่มีตัวกรองคำนำหน้าที่เหมาะสม เพื่อรับเฉพาะข้อมูลที่ ที่เกี่ยวข้องกับสถานะปัจจุบันของแอปพลิเคชัน
  5. ติดตั้งใช้งาน onDataChanged(), onMessageReceived() onCapabilityChanged() หรือเมธอดจาก ChannelClient.ChannelCallback ขึ้นอยู่กับอินเทอร์เฟซที่คุณใช้ เราจะเรียกวิธีการเหล่านี้ใน เทรดหลัก หรือคุณจะระบุ Looper ที่กำหนดเองโดยใช้ WearableOptions ก็ได้

นี่คือตัวอย่างที่นำ DataClient.OnDataChangedListener ไปใช้

Kotlin

class MainActivity : Activity(), DataClient.OnDataChangedListener {

    public override fun onResume() {
        Wearable.getDataClient(this).addListener(this)
    }

    override fun onPause() {
        Wearable.getDataClient(this).removeListener(this)
    }

    override fun onDataChanged(dataEvents: DataEventBuffer) {
        dataEvents.forEach { event ->
            if (event.type == DataEvent.TYPE_DELETED) {
                Log.d(TAG, "DataItem deleted: " + event.dataItem.uri)
            } else if (event.type == DataEvent.TYPE_CHANGED) {
                Log.d(TAG, "DataItem changed: " + event.dataItem.uri)
            }
        }
    }
}

Java

public class MainActivity extends Activity implements DataClient.OnDataChangedListener {

    @Override
    public void onResume() {
        Wearable.getDataClient(this).addListener(this);
    }

    @Override
    protected void onPause() {
        Wearable.getDataClient(this).removeListener(this);
    }

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_DELETED) {
                Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
            } else if (event.getType() == DataEvent.TYPE_CHANGED) {
                Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
            }
        }
    }
}

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

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

รูปแบบที่พบบ่อยคือการลงทะเบียน Listener ด้วยเส้นทางหรือคำนำหน้าเส้นทางที่เฉพาะเจาะจง ในonResume()ของกิจกรรม และนำ Listener ในกิจกรรม onPause() วิธี การใช้ Listener ในรูปแบบนี้ทำให้แอปของคุณมีความเปิดกว้างมากขึ้น รับกิจกรรม ปรับปรุงการออกแบบและประสิทธิภาพ