Menampilkan pembaruan dinamis dalam kartu

Mulai Kartu 1.2, Anda dapat melakukan streaming pembaruan data platform menggunakan ekspresi dinamis. Kemudian, Anda dapat mengaitkan pembaruan ini dengan animasi di kartu Anda. Aplikasi Anda mendapatkan pembaruan untuk nilai ini setiap detik.

Dengan menggunakan ekspresi dinamis, Anda tidak perlu me-refresh seluruh kartu saat kontennya berubah. Untuk membuat pengalaman yang lebih menarik di kartu, animasikan objek dinamis tersebut.

Mengaitkan ekspresi dinamis dengan sumber data

Namespace androidx.wear.protolayout dan androidx.wear.protolayout.material berisi banyak class yang kolomnya menerima ekspresi dinamis. Beberapa contohnya meliputi:

Untuk menggunakan ekspresi dinamis sebagai kemungkinan nilai untuk elemen dalam kartu Anda, gunakan jenis properti dinamis *Prop yang sesuai pada elemen dan teruskan sumber data ke metode setDynamicValue() class builder jenis properti dinamis.

Kartu mendukung jenis properti dinamis ini:

Saat menggunakan ekspresi dinamis yang memengaruhi dimensi fisik—nilai apa pun dalam kartu kecuali warna—Anda juga harus menentukan kumpulan batasan terkait, seperti format string. Batasan ini memungkinkan perender sistem menentukan jumlah ruang maksimum yang dapat menempati nilai dalam kartu Anda. Biasanya, Anda akan menentukan batasan ini pada tingkat elemen, bukan pada tingkat ekspresi dinamis, dengan memanggil metode yang dimulai dengan setLayoutConstraintsForDynamic*.

Cuplikan kode berikut menunjukkan cara menampilkan pembaruan pada detak jantung menggunakan 3 digit, dengan nilai penggantian --:

override fun onTileRequest(requestParams: RequestBuilders.TileRequest) =
    Futures.immediateFuture(
        Tile.Builder()
            .setResourcesVersion(RESOURCES_VERSION)
            .setFreshnessIntervalMillis(60 * 60 * 1000) // 60 minutes
            .setTileTimeline(
                Timeline.fromLayoutElement(
                    Text.Builder(
                        this,
                        TypeBuilders.StringProp.Builder("--")
                            .setDynamicValue(
                                PlatformHealthSources.heartRateBpm()
                                    .format()
                                    .concat(DynamicBuilders.DynamicString.constant(" bpm"))
                            )
                            .build(),
                        TypeBuilders.StringLayoutConstraint.Builder("000").build(),
                    )
                        .build()
                )
            )
            .build()
    )

Menggunakan sejumlah kecil ekspresi dalam satu kartu

Wear OS menetapkan batas jumlah ekspresi yang dapat dimiliki satu kartu. Jika kartu berisi terlalu banyak ekspresi dinamis total, nilai dinamis akan diabaikan, dan sistem akan kembali ke nilai statis yang Anda berikan ke jenis properti dinamis masing-masing.

Menggabungkan data dinamis ke dalam objek status

Anda dapat menggabungkan kumpulan pembaruan terbaru dari sumber data ke dalam status, yang akan diteruskan ke kartu untuk rendering nilai.

Untuk menggunakan informasi status di kartu Anda, selesaikan langkah-langkah berikut:

  1. Tetapkan kumpulan kunci yang mewakili berbagai nilai dari status kartu Anda. Contoh ini membuat kunci untuk asupan air dan catatan:

    Kotlin

    companion object {
        val KEY_WATER_INTAKE = AppDataKey<DynamicInt32>("water_intake")
        val KEY_NOTE = AppDataKey<DynamicString>("note")
    }

    Java

    private static final AppDataKey<DynamicInt32> KEY_WATER_INTAKE =
        new AppDataKey<DynamicInt32>("water_intake");
    private static final AppDataKey<DynamicString> KEY_NOTE =
        new AppDataKey<DynamicString>("note");
  2. Dalam penerapan onTileRequest(), panggil setState() dan tetapkan pemetaan awal dari setiap kunci ke nilai data dinamis tertentu:

    Kotlin

    override fun onTileRequest(requestParams: TileRequest):
            ListenableFuture<Tile> {
        val state = State.Builder()
            .addKeyToValueMapping(KEY_WATER_INTAKE,
                DynamicDataBuilders.DynamicDataValue.fromInt(200))
            .addKeyToValueMapping(KEY_NOTE,
                DynamicDataBuilders.DynamicDataValue.fromString("Note about day"))
        .build()
        // ...
    
        return Futures.immediateFuture(Tile.Builder()
            // Set resources, timeline, and other tile properties.
            .setState(state)
            .build()
        )

    Java

    @Override
    protected ListenableFuture<Tile> onTileRequest(
                ListenableFuture<Tile> {
        State state = new State.Builder()
            .addKeyToValueMapping(KEY_WATER_INTAKE,
                DynamicDataBuilders.DynamicDataValue.fromInt(200))
            .addKeyToValueMapping(KEY_NOTE,
                DynamicDataBuilders.DynamicDataValue.fromString("Note about day"))
        .build();
        // ...
    
        return Futures.immediateFuture(Tile.Builder()
            // Set resources, timeline, and other tile properties.
            .setState(state)
            .build()
        );
    }
  3. Saat Anda membuat tata letak, di tempat yang diinginkan untuk menampilkan data ini dari status, gunakan objek jenis Dynamic*. Anda juga dapat memanggil animate() untuk menampilkan animasi dari nilai sebelumnya ke nilai saat ini:

    Kotlin

    DynamicInt32.from(KEY_WATER_INTAKE).animate()

    Java

    DynamicInt32.from(KEY_WATER_INTAKE).animate();
  4. Jika diperlukan, Anda juga dapat memperbarui status dengan nilai baru. Status ini dapat menjadi bagian dari LoadAction kartu.

    Dalam contoh ini, nilai asupan air diperbarui menjadi 400:

    Kotlin

    val loadAction = LoadAction.Builder()
        .setRequestState(
            State.Builder()
                .addKeyToValueMapping(
                    KEY_WATER_INTAKE,
                    DynamicDataBuilders.DynamicDataValue.fromInt(400)
                )
                .build()
        )
        .build()

    Java

    LoadAction loadAction = new LoadAction.Builder()
        .setRequestState(
            new State.Builder()
                .addKeyToValueMapping(
                    KEY_WATER_INTAKE,
                    DynamicDataBuilders.DynamicDataValue.fromInt(400)
                ).build()
        ).build();