Mostra aggiornamenti periodici nei riquadri

Crea riquadri con contenuti che cambiano con il passare del tempo.

Utilizzare le sequenze temporali

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

Cronologia del riquadro con due voci, ognuna con un layout.
Diagramma della sequenza temporale dei riquadri.

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 progressi di fitness della giornata mostra sempre lo stesso layout dei progressi, anche se potresti modificarlo per mostrare valori diversi. In questi casi, non sai in anticipo quando i contenuti potrebbero cambiare.

Consulta il seguente esempio di un riquadro con un singolo TimelineEntry:

override fun onTileRequest(
    requestParams: RequestBuilders.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(simpleLayout(this)))
            .build()
    return Futures.immediateFuture(tile)
}

Voci della sequenza temporale con limiti di tempo

Un TimelineEntry può definire facoltativamente un periodo di validità, consentendo a un riquadro di modificare il layout in un momento noto senza richiedere all'app di eseguire il push di 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 Tiles consente periodi di validità sovrapposti, in cui viene mostrata la schermata con il periodo di tempo rimanente più breve. Viene visualizzato un solo evento alla volta.

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

override fun onTileRequest(
    requestParams: RequestBuilders.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(
        TimelineBuilders.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(
            TimelineBuilders.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.
                    TimelineBuilders.TimeInterval.Builder()
                        .setEndMillis(meeting.dateTimeMillis)
                        .build()
                )
                .build()
        )
    }

    val tile =
        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 po' di tempo. Ad esempio, un riquadro meteo che mostra la stessa temperatura per tutto il giorno 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, potresti aggiornarne i contenuti ogni ora, come mostrato nel seguente esempio di codice:

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

Quando imposti un intervallo di aggiornamento, il sistema chiama onTileRequest() poco dopo la fine dell'intervallo. 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 calendario e, se il riquadro non è stato aggiornato, continuerà a mostrare la riunione eliminata. In questo caso, richiedi un aggiornamento da qualsiasi punto del codice dell'applicazione, come mostrato nel seguente esempio di codice:

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

Scegliere un flusso di lavoro di aggiornamento

Utilizza queste best practice per determinare come configurare gli aggiornamenti dei riquadri:

  • Se l'aggiornamento è prevedibile, ad esempio se riguarda 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 l'aggiornamento può essere calcolato sul dispositivo in un breve periodo di tempo, ad esempio l'aggiornamento della posizione di un'immagine su un riquadro dell'alba, utilizza onTileRequest().

    Questa opzione è particolarmente utile quando devi generare tutte le immagini in anticipo. Se devi generare una nuova immagine in un momento futuro, chiama setFreshnessIntervalMillis().

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

  • Se l'aggiornamento è in risposta a un evento esterno, ad esempio l'accensione delle luci , la ricezione di un'email o l'aggiornamento di una nota, invia un messaggio Firebase Cloud Messaging (FCM) per riattivare l'app, quindi esegui il push degli aggiornamenti sul riquadro.

  • Se il processo di sincronizzazione dei dati dei riquadri potrebbe essere costoso:

    1. Pianifica una sincronizzazione dei dati.
    2. Avvia un timer per 1-2 secondi.
    3. Se ricevi un aggiornamento da un'origine dati remota prima della scadenza del tempo, mostra il valore aggiornato dalla sincronizzazione dei dati. In caso contrario, mostra un valore locale memorizzato nella cache.