Показывать периодические обновления на плитках

Создавайте плитки с содержимым, которое меняется с течением времени.

Работа с временными шкалами

Временная шкала состоит из одного или нескольких экземпляров TimelineEntry , каждый из которых содержит макет, отображаемый в течение определенного интервала времени. Всем плиткам нужна временная шкала.

Схема временной шкалы плитки

Одновходная плитка

Часто плитку можно описать с помощью одного TimelineEntry . Макет фиксирован, и меняется только информация внутри макета. Например, плитка, показывающая ваш прогресс в фитнесе за день, всегда отображает один и тот же макет прогресса, хотя вы можете настроить этот макет, чтобы отображать другие значения. В таких случаях вы заранее не знаете, когда содержимое может измениться.

См. следующий пример плитки с одним TimelineEntry :

Котлин

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

Ява

@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);
}

Записи временной шкалы с привязкой ко времени

TimelineEntry может дополнительно определять период действия, позволяя плитке менять свой макет в известное время, не требуя от приложения отправки новой плитки.

Каноническим примером является плитка повестки дня, временная шкала которой содержит список предстоящих событий. Каждое предстоящее событие содержит период действия, указывающий, когда его показывать.

API плиток позволяет перекрывать периоды действия, при этом отображается экран с наименьшим оставшимся периодом времени. Одновременно отображается только одно событие.

Разработчики могут предоставить резервную запись по умолчанию. Например, плитка повестки дня может иметь плитку с бесконечным периодом действия, которая используется, если никакая другая запись временной шкалы недействительна, как показано в следующем примере кода:

Котлин

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

Ява

@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);
}

Обновить плитку

Информация, отображаемая на плитке, может исчезнуть через некоторое время. Например, плитка погоды, на которой в течение дня отображается одна и та же температура, неточна.

Чтобы справиться с данными с истекающим сроком действия, установите интервал обновления во время создания плитки, который определяет, как долго плитка действительна. В примере плитки погоды вы можете обновлять ее содержимое каждый час, как показано в следующем примере кода:

Котлин

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

Ява

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

Когда вы устанавливаете интервал обновления, система вызывает onTileRequest() вскоре после окончания интервала. Если вы не установите интервал обновления, система не вызовет onTileRequest() .

Срок действия плитки также может истечь из-за внешнего события. Например, пользователь может удалить собрание из своего календаря, и если плитка не обновилась, на плитке все равно будет отображаться это удаленное собрание. В этом случае запросите обновление из любого места кода приложения, как показано в следующем примере кода:

Котлин

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

Ява

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

Выберите рабочий процесс обновления

Используйте эти рекомендации, чтобы определить, как настроить обновления плиток:

  • Если обновление предсказуемо (например, если оно касается следующего события в календаре пользователя), используйте временную шкалу.
  • При получении данных платформы используйте привязку данных, чтобы система автоматически обновляла данные.
  • Если обновление можно рассчитать на устройстве за небольшой промежуток времени (например, обновление положения изображения на плитке восхода солнца), используйте onTileRequest() .

    Это особенно полезно, когда вам нужно заранее сгенерировать все изображения. Если вам понадобится создать новое изображение в будущем, вызовите setFreshnessIntervalMillis() .

  • Если вы постоянно выполняете более интенсивную фоновую работу, например опрос данных о погоде, используйте WorkManager и отправляйте обновления на свою плитку.

  • Если обновление происходит в ответ на внешнее событие, например включение света, получение электронного письма или обновление заметки, отправьте сообщение Firebase Cloud Messaging (FCM), чтобы ваше приложение снова стало активным, а затем отправьте обновления на плитку.

  • Если процесс синхронизации данных листов может оказаться дорогостоящим, выполните следующие действия:

    1. Запланируйте синхронизацию данных.
    2. Запустите таймер на 1-2 секунды.
    3. Если вы получили обновление из удаленного источника данных до истечения времени, покажите обновленное значение из синхронизации данных. В противном случае отобразите кэшированное локальное значение.
{% дословно %} {% дословно %} {% дословно %} {% дословно %}