Mostra aggiornamenti periodici nei riquadri

Crea riquadri con contenuti che cambiano nel tempo.

Utilizzare le tempistiche

Una sequenza temporale è composta da una o più istanze TimelineEntry, ognuna delle quali contiene un layout che viene visualizzato durante un intervallo di tempo specifico. Tutti i riquadri devono avere una sequenza temporale.

Diagramma della sequenza temporale del riquadro

Riquadri a ingresso singolo

Spesso un riquadro può essere descritto con un singolo TimelineEntry. Il layout è fisso e cambiano solo le informazioni al suo interno. Ad esempio, un riquadro che mostra i tuoi progressi durante la giornata mostra sempre lo stesso layout dei progressi, anche se puoi modificarlo per mostrare valori diversi. In questi casi, non sei a conoscenza in anticipo quando i contenuti potrebbero cambiare.

Vedi l'esempio seguente di un riquadro con un singolo TimelineEntry:

Kotlin

override fun onTileRequest(
    requestParams: TileRequest
): ListenableFuture<Tile> {
    val tile = Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)

        // We add a single timeline entry when our layout is fixed, and
        // we don't know in advance when its contents might change.
        .setTileTimeline(
            Timeline.fromLayoutElement(...)
        ).build()
    return Futures.immediateFuture(tile)
}

Java

@Override
protected ListenableFuture<Tile> onTileRequest(
       @NonNull TileRequest requestParams
) {
   Tile tile = new Tile.Builder()
       .setResourcesVersion(RESOURCES_VERSION)
       
       // We add a single timeline entry when our layout is fixed, and
       // we don't know in advance when its contents might change.
       .setTileTimeline(
            Timeline.fromLayoutElement(...)
       ).build();
   return Futures.immediateFuture(tile);
}

Voci di sequenza temporale con vincoli temporali

Un TimelineEntry può facoltativamente definire un periodo di validità, consentendo a un riquadro di modificare il proprio layout in un momento noto senza che l'app debba inviare un nuovo riquadro.

L'esempio canonico è un riquadro dell'agenda la cui sequenza temporale contiene un elenco di eventi imminenti. Ogni evento imminente contiene un periodo di validità per indicare quando mostrarlo.

L'API dei riquadri consente di sovrapporre periodi di validità, dove viene mostrata la schermata con il periodo di tempo più breve. Viene visualizzato un solo evento alla volta.

Gli sviluppatori possono fornire una voce di riserva predefinita. Ad esempio, il riquadro dell'agenda potrebbe avere un riquadro con un periodo di validità infinita, che viene utilizzato se nessun'altra voce della sequenza temporale è valida, come mostrato nel seguente esempio di codice:

Kotlin

public override fun onTileRequest(
    requestParams: TileRequest
): ListenableFuture<Tile> {
    val timeline = Timeline.Builder()

    // Add fallback "no meetings" entry
    // Use the version of TimelineEntry that's in androidx.wear.protolayout.
    timeline.addTimelineEntry(TimelineEntry.Builder()
        .setLayout(getNoMeetingsLayout())
        .build()
    )

    // Retrieve a list of scheduled meetings
    val meetings = MeetingsRepo.getMeetings()
    // Add a timeline entry for each meeting
    meetings.forEach { meeting ->
        timeline.addTimelineEntry(TimelineEntry.Builder()
            .setLayout(getMeetingLayout(meeting))
            .setValidity(
                // The tile should disappear when the meeting begins
                // Use the version of TimeInterval that's in
                // androidx.wear.protolayout.
                TimeInterval.Builder()
                    .setEndMillis(meeting.dateTimeMillis).build()
            ).build()
        )
    }

    val tile = Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setTileTimeline(timeline.build())
        .build()
    return Futures.immediateFuture(tile)
}

Java

@Override
protected ListenableFuture<Tile> onTileRequest(
       @NonNull RequestBuilders.TileRequest requestParams
) {
   Timeline.Builder timeline = new Timeline.Builder();
   // Add fallback "no meetings" entry
   // Use the version of TimelineEntry that's in androidx.wear.protolayout.
   timeline.addTimelineEntry(new TimelineEntry.Builder().setLayout(getNoMeetingsLayout()).build());
   // Retrieve a list of scheduled meetings
   List<Meeting> meetings = MeetingsRepo.getMeetings();
   // Add a timeline entry for each meeting
   for(Meeting meeting : meetings) {
        timeline.addTimelineEntry(new TimelineEntry.Builder()
            .setLayout(getMeetingLayout(meeting))
            .setValidity(
                // The tile should disappear when the meeting begins
                // Use the version of TimeInterval that's in
                // androidx.wear.protolayout.
                new TimeInterval.builder()
                    .setEndMillis(meeting.getDateTimeMillis()).build()
            ).build()
        );
    }

    Tile tile = new Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setTileTimeline(timeline.build())
        .build();
    return Futures.immediateFuture(tile);
}

Aggiornare un riquadro

Le informazioni mostrate su un riquadro potrebbero scadere dopo un certo periodo di tempo. Ad esempio, un riquadro meteo che mostra la stessa temperatura durante la giornata non è preciso.

Per gestire i dati in scadenza, imposta un intervallo di aggiornamento al momento della creazione di un riquadro, che specifica per quanto tempo il riquadro è valido. Nell'esempio del riquadro Meteo, puoi aggiornarne il contenuto ogni ora, come mostrato nel seguente esempio di codice:

Kotlin

override fun onTileRequest(requestParams: RequestBuilders.TileRequest) =
    Futures.immediateFuture(Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setFreshnessIntervalMillis(60 * 60 * 1000) // 60 minutes
        .setTileTimeline(Timeline.fromLayoutElement(
            getWeatherLayout())
        ).build()
    )

Java

@Override
protected ListenableFuture<Tile> onTileRequest(
       @NonNull TileRequest requestParams
) {
    return Futures.immediateFuture(new Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setFreshnessIntervalMillis(60 * 60 * 1000) // 60 minutes
        .setTimeline(Timeline.fromLayoutElement(
            getWeatherLayout())
        ).build());
}

Quando imposti un intervallo di aggiornamento, il sistema chiama onTileRequest() poco dopo il suo termine. Se non imposti un intervallo di aggiornamento, il sistema non chiama onTileRequest().

Un riquadro può scadere anche a causa di un evento esterno. Ad esempio, un utente potrebbe rimuovere una riunione dal proprio calendario e, se il riquadro non veniva aggiornato, mostrerà comunque quella riunione eliminata. In questo caso, richiedi un aggiornamento da qualsiasi punto del codice dell'applicazione, come mostrato nel seguente esempio di codice:

Kotlin

fun eventDeletedCallback() {
     TileService.getUpdater(context)
             .requestUpdate(MyTileService::class.java)
}

Java

public void eventDeletedCallback() {
   TileService.getUpdater(context)
           .requestUpdate(MyTileService.class);
}

Scegli un flusso di lavoro di aggiornamento

Per determinare come configurare gli aggiornamenti dei riquadri, utilizza queste best practice:

  • Se l'aggiornamento è prevedibile, ad esempio per l'evento successivo nel calendario dell'utente, utilizza una sequenza temporale.
  • Quando recuperi i dati della piattaforma, utilizza l'associazione di dati in modo che il sistema aggiorni automaticamente i dati.
  • Se è possibile calcolare l'aggiornamento sul dispositivo in un breve periodo di tempo, ad esempio aggiornare la posizione di un'immagine su un riquadro luce graduale, utilizza onTileRequest().

    Questa opzione è particolarmente utile quando è necessario generare tutte le immagini in anticipo. Se in futuro avrai bisogno di generare una nuova immagine, chiama setFreshnessIntervalMillis().

  • Se esegui ripetutamente un lavoro in background più intensivo, ad esempio il polling per i dati meteo, utilizza WorkManager ed esegui il push degli aggiornamenti nel riquadro.

  • Se l'aggiornamento è in risposta a un evento esterno, ad esempio se le luci si accendono, la ricezione di un'email o l'aggiornamento di una nota, invia un messaggio Firebase Cloud Messaggiging (FCM) per riattivare l'app, quindi invia gli aggiornamenti al riquadro.

  • Se il processo di sincronizzazione dei dati dei riquadri potrebbe essere costoso, procedi nel seguente modo:

    1. Pianificare una sincronizzazione dei dati.
    2. Avvia un timer di 1-2 secondi.
    3. Se ricevi un aggiornamento da un'origine dati remota prima che il tempo scada, mostra il valore aggiornato dalla sincronizzazione dei dati. In caso contrario, mostra un valore locale memorizzato nella cache.