Dynamische Updates in Kacheln anzeigen

Ab Version 1.2 von „Kacheln“ können Sie Plattformdatenaktualisierungen mit dynamischen Ausdrücken streamen. Sie können diese Aktualisierungen dann mit Animationen in Ihren Kacheln verknüpfen. Dieser Wert wird in Ihrer App jede Sekunde aktualisiert.

Wenn Sie dynamische Ausdrücke verwenden, müssen Sie die gesamte Kachel nicht aktualisieren, wenn sich ihr Inhalt ändert. Animieren Sie diese dynamischen Objekte, um Ihre Ansichten ansprechender zu gestalten.

Dynamische Ausdrücke mit Datenquellen verknüpfen

Die Namespaces androidx.wear.protolayout und androidx.wear.protolayout.material enthalten viele Klassen, deren Felder dynamische Ausdrücke akzeptieren. Beispiele:

Wenn Sie einen dynamischen Ausdruck als möglichen Wert für ein Element in Ihrer Kachel verwenden möchten, verwenden Sie den entsprechenden *Prop-Typ der dynamischen Property des Elements und geben Sie die Datenquelle an die setDynamicValue()-Methode der Builder-Klasse des dynamischen Property-Typs weiter.

Für Kacheln werden die folgenden dynamischen Attributtypen unterstützt:

Wenn Sie einen dynamischen Ausdruck verwenden, der sich auf physische Dimensionen auswirkt (alle Werte in einer Kachel mit Ausnahme der Farbe), müssen Sie auch eine Reihe von zugehörigen Einschränkungen angeben, z. B. ein Stringformat. Anhand dieser Einschränkungen kann der System-Renderer den maximalen Platz ermitteln, den ein Wert in Ihrer Kachel einnehmen kann. Normalerweise geben Sie diese Einschränkungen auf Elementebene an, nicht auf Ebene des dynamischen Ausdrucks. Dazu rufen Sie eine Methode auf, die mit setLayoutConstraintsForDynamic* beginnt.

Im folgenden Code-Snippet wird gezeigt, wie Aktualisierungen der Herzfrequenz mit drei Ziffern und einem Fallback-Wert von -- angezeigt werden:

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

Verwenden Sie in einer einzelnen Kachel nur eine kleine Anzahl von Ausdrücken.

In Wear OS ist die Anzahl der Ausdrücke, die eine einzelne Kachel haben kann, begrenzt. Wenn eine Kachel insgesamt zu viele dynamische Ausdrücke enthält, werden dynamische Werte ignoriert und das System greift auf die statischen Werte zurück, die Sie für die jeweiligen dynamischen Property-Typen angeben.

Dynamische Daten in einem Zustandsobjekt zusammenführen

Sie können die neuesten Aktualisierungen aus Datenquellen in einem Status zusammenfassen, den Sie zur Wertdarstellung an Ihre Kachel übergeben.

So verwenden Sie Statusinformationen in Ihren Kacheln:

  1. Legen Sie eine Reihe von Schlüsseln fest, die die verschiedenen Werte des Status Ihrer Kachel darstellen. In diesem Beispiel werden Schlüssel für die Wasseraufnahme und eine Notiz erstellt:

    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. Rufen Sie in Ihrer Implementierung von onTileRequest() setState() auf und legen Sie erste Zuordnungen von jedem Schlüssel zu einem bestimmten dynamischen Datenwert fest:

    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. Verwenden Sie beim Erstellen des Layouts an einer Stelle, an der Sie diese Daten aus dem Bundesstaat anzeigen möchten, ein Objekt vom Typ Dynamic*. Sie können auch animate() aufrufen, um eine Animation vom vorherigen zum aktuellen Wert anzuzeigen:

    Kotlin

    DynamicInt32.from(KEY_WATER_INTAKE).animate()

    Java

    DynamicInt32.from(KEY_WATER_INTAKE).animate();
  4. Bei Bedarf können Sie den Status auch mit neuen Werten aktualisieren. Dies kann Teil der LoadAction einer Kachel sein.

    In diesem Beispiel wird der Wert für die Wasseraufnahme auf 400 aktualisiert:

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