Pokazuj dynamiczne aktualizacje w kafelkach

Od wersji 1.2 kafelków możesz przesyłać strumieniowo aktualizacje danych platformy za pomocą dynamicznych wyrażeń. Następnie możesz powiązać te aktualizacje z animacjami w swoich kafelkach. Aplikacja otrzymuje aktualizacje tej wartości co sekundę.

Dzięki wyrażeniom dynamicznym nie musisz odświeżać całego kafelka, gdy zmienia się jego zawartość. Aby zwiększyć zaangażowanie użytkowników, animuj dynamiczne obiekty w kafelkach.

Powiązywanie wyrażeń dynamicznych ze źródłami danych

Przestrzenie nazw androidx.wear.protolayoutandroidx.wear.protolayout.material zawierają wiele klas, których pola akceptują wyrażenia dynamiczne. Oto kilka przykładów:

Aby użyć wyrażenia dynamicznego jako możliwej wartości elementu w kafelku, użyj odpowiedniego *Prop dynamicznego typu właściwości elementu i przekaż źródło danych do metody setDynamicValue() klasy konstruktora dynamicznego typu właściwości.

Kafelki obsługują te typy właściwości dynamicznych:

Jeśli używasz wyrażenia dynamicznego, które wpływa na wymiary fizyczne (dowolna wartość w kafelku z wyjątkiem koloru), musisz też określić zestaw powiązanych ograniczeń, np. format ciągu tekstowego. Te ograniczenia pozwalają modułowi renderującemu systemu określić maksymalną ilość miejsca, jaką wartość może zajmować w kafelku. Zwykle te ograniczenia określa się na poziomie elementu, a nie na poziomie wyrażenia dynamicznego, wywołując metodę zaczynającą się od znaku setLayoutConstraintsForDynamic*.

Poniższy fragment kodu pokazuje, jak wyświetlać aktualizacje tętna za pomocą 3 cyfr z wartością domyślną --:

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

Używaj niewielkiej liczby wyrażeń w ramach jednego kafelka.

Wear OS ogranicza liczbę wyrażeń, które może zawierać jeden kafel. Jeśli kafel zawiera zbyt wiele dynamicznych wyrażeń, wartości dynamiczne są ignorowane, a system wraca do wartości statycznych, które podajesz w przypadku poszczególnych typów właściwości dynamicznych.

Zbieranie danych dynamicznych w obiekcie stanu

Najnowszy zestaw aktualizacji ze źródeł danych możesz skonsolidować w stanie, który przekazujesz do kafelka w celu renderowania wartości.

Aby używać informacji o stanie w kafelkach, wykonaj te czynności:

  1. Utwórz zestaw kluczy reprezentujących różne wartości stanu kafelka. W tym przykładzie tworzymy klucze dla ilości wypitej wody i notatki qqq:

    companion object {
        val KEY_WATER_INTAKE = intAppDataKey("key_water_intake")
        val KEY_NOTE = stringAppDataKey("key_note")
    }

  2. W implementacji onTileRequest() wywołaj funkcję setState() i utwórz wstępne mapowania każdego klucza na konkretną dynamiczną wartość danych:

    override fun onTileRequest(
        requestParams: RequestBuilders.TileRequest
    ): ListenableFuture<Tile?> {
        // If the tile hasn't had any state set yet, use the default values
        val state =
            if (requestParams.currentState.keyToValueMapping.isNotEmpty())
                requestParams.currentState
            else
                StateBuilders.State.Builder()
                    .setStateMap(
                        dynamicDataMapOf(
                            KEY_WATER_INTAKE mapTo 200,
                            KEY_NOTE mapTo "Good"
                        )
                    )
                    .build()
    
        return Futures.immediateFuture(
            Tile.Builder()
                // Set resources, timeline, and other tile properties.
                .setState(state)
                .build()
        )
    }

  3. Podczas tworzenia układu w miejscu, w którym chcesz wyświetlać te dane ze stanu, użyj obiektu typu Dynamic*. Możesz też wywołać funkcję animate(), aby wyświetlić animację od poprzedniej do bieżącej wartości:

    val waterIntakeValue =
        DynamicBuilders.DynamicInt32.from(KEY_WATER_INTAKE)

  4. W razie potrzeby możesz też zaktualizować stan, podając nowe wartości. Może to być część LoadAction kafelka.

    W tym przykładzie wartość spożycia wody jest aktualizowana do 400:

    val loadAction =
        loadAction(
            dynamicDataMapOf(
                KEY_WATER_INTAKE mapTo 400,
                KEY_NOTE mapTo "Outstanding"
            )
        )