Glanceがbetaになったぞ

# はじめに
こんにちは、どすこいです。
先日[Glanceのbeta-01](https://developer.android.com/jetpack/androidx/releases/glance#version_100_2)がリリースされましたね。

Glanceを早くプロダクションで使いたい身としては、とても嬉しいことです。
ということで早速触っていきましょう。
alphaからの違いやbetaになってできるようになったことを紹介していこうと思います。

## setup
```groovy:app/build.gradle
dependencies {
    ...
    implementation "androidx.glance:glance-appwidget:1.0.0-beta01"
    ...
}
```

# ContentからprovideGlanceへ
Glanceのエントリポイントが以下のような変更になりました。
## 変更点

- エントリポイントがComposable関数じゃなくなった
- ContextとGlanceIdが引数で渡されるように
    - GlanceIdはAppWidgetIdのwrapper
- overrideするメソッド自体がComposable関数ではなくなったため、`provideContent`を使ってComposableを呼び出す必要がある


### Beta版
```kotlin
override suspend fun provideGlance(context: Context, id: GlanceId) = provideContent {
  ...
}
```

### Alpha版
```kotlin
@Composable
override fun Content() {
  ...
}
```

# GlanceThemeの追加
Themeが追加されました。
Composeを触ってる方ならわかると思いますが、Compose側には`MaterialTheme`というものがありアプリ全体でのテーマを統一することができました。
alphaまでのGlanceにはThemeを指定するものがありませんでしたが、betaになり`GlanceTheme`というものが追加されました。

## コード
```kotlin
override suspend fun provideGlance(context: Context, id: GlanceId) = provideContent {
  GlanceTheme(colors = ...) {
    ...
  }
}
```

GlanceThemeの引数は
- `colors: ColorProviders`
- `content: @GlanceComposable @Composable () -> Unit`
の2つなので、色のThemeのみ指定できるようになっています。
:::note warn
typographyの指定はまだできないようです。
:::

## ColorProvider
ColorProviderはGlanceでのみ登場します。
ColorProviderのコンストラクタには、`androidx.compose.ui.graphics.Color`と`@ColorRes`を渡すことができるようになっており、経緯はわかりませんがGlanceでの色の指定に必要になってきます。

## ColorProviders
ColorProvidersもGlanceでのみ登場します。
Material3のcolor shemeを提供するためのクラスです。

```kotlin
sealed class ColorProviders(
    val primary: ColorProvider,
    val onPrimary: ColorProvider,
    val primaryContainer: ColorProvider,
    val onPrimaryContainer: ColorProvider,
    val secondary: ColorProvider,
    val onSecondary: ColorProvider,
    ...
)
```
sealed classとなっており、ColorProvidersを直接インスタンス化することは不可能なようです。
独自のcolor schemeを使いたい場合は以下のメソッドを使ってください。

```kotlin
fun colorProviders(
    primary: ColorProvider,
    onPrimary: ColorProvider,
    primaryContainer: ColorProvider,
    onPrimaryContainer: ColorProvider,
    secondary: ColorProvider,
    onSecondary: ColorProvider,
    ...
)
```

こちらは中で`CustomColorProviders`というクラスを作成しています。`CustomColorProviders`は上記の`ColorProviders`を継承しています。`inner class`なので、上記のメソッドを通してでないと`ColorProviders`は作れません。

また`DynamicThemeColorProviders`というものも存在します。こちらも`ColorProviders`を継承しています。

>Creates a set of color providers that represents a Material 3 style dynamic color theme. On devices that support it, this theme is derived from the user specific platform colors, on other devices this falls back to the Material baseline theme.

>Material 3スタイルのダイナミックカラーテーマを表すカラープロバイダーのセットを作成します。これをサポートするデバイスでは、このテーマはユーザー固有のプラットフォームカラーから派生し、その他のデバイスでは、マテリアル・ベースライン・テーマに戻されます。(DeepL)

:::note warn
デフォルトでは`DynamicThemeColorProviders`が使われているため、独自のcolor schemeを使っているプロダクトは`GlanceTheme`を使う際は注意してください。
:::

# glance-material, glance-material3の追加
上記の`ColorProviders`は`androidx.glance:glance-appwidget`に含まれているものですが、今回のアップデートで、`glance-material`と`glance-material3`も追加されました。
今回の追加ではそれぞれのMaterial Designのカラーパレットに対応した、`ColorProvider`を提供するだけのものとなっていますが、そのうちTypographyの提供などもしてくれそうですね。

## glance-material
### 導入
```groovy:app/build.gradle
    ...
    implementation "androidx.compose.material:material:1.4.3"
    implementation "androidx.glance:glance-material:1.0.0-beta01"
    ...
```
:::note warn
glance-materialの内部でcomposeのmaterialも使っているため追加をお忘れなく。
:::

### 使ってみる
上記にもありますが、glance-materialができるのはThemeの提供ではなく、あくまで`ColorProviders`の提供までです。(beta-01時点)
なので`GlanceTheme`のcolorsに対して、glance-materialが提供している`ColorProviders`を適用する方になります。
```kotlin
GlanceTheme(
    colors = androidx.glance.material.ColorProviders(
        light = Colors(...),
        dark = Colors(...),
    )
) {
}
```

ダークテーマに対応していない場合は以下でもOKです。
```kotlin
GlanceTheme(
    colors = androidx.glance.material.ColorProviders(
        colors = Colors(...)
    )
) {
}
```

ここで使っている`Colors`はComposeのMaterialに内包されているもので、Material2のカラーパレットです。

## glance-material3
### 導入
```groovy:app/build.gradle
    ...
    implementation "androidx.compose.material3:material3:1.1.0"
    implementation "androidx.glance:glance-material3:1.0.0-beta01"
    ...
```
:::note warn
glance-material3の内部でcomposeのmaterial3も使っているため追加をお忘れなく。
:::

### 使ってみる
上記にもありますが、glance-material3ができるのはThemeの提供ではなく、あくまで`ColorProviders`の提供までです。(beta-01時点)
なので`GlanceTheme`のcolorsに対して、glance-material3が提供している`ColorProviders`を適用する方になります。
```kotlin
GlanceTheme(
    colors = androidx.glance.material3.ColorProviders(
        light = ColorSheme(...),
        dark = ColorScheme(...),
    )
) {
}
```

ダークテーマに対応していない場合は以下でもOKです。
```kotlin
GlanceTheme(
    colors = androidx.glance.material3.ColorProviders(
        scheme = ColorSheme(...)
    )
) {
}
```
ここで使っている`ColorScheme`はComposeのMaterial3に内包されているもので、Material3のカラーパレットです。


# Actionの追加
`LambdaAction`が追加されました。
alphaまでのGlanceでは単純なactionを実行するだけでも`ActionCallback`を継承したクラスを作る必要がありました。
しかし今回のアップデータとで、単純なアクションを実行するだけであれば`LambdaAction`を使えばよくなりました。

```kotlin
Button(
    text = "click here!",
    onClick = action {
        ...
    }
)
```

`action`メソッドは、内部で`LambdaAction`を生成してくれるものです。
```kotlin
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
class LambdaAction(
    val key: String,
    val block: () -> Unit,
) : Action {
    override fun toString() = "LambdaAction($key, ${block.hashCode()})"
}

/**
 * Create an [Action] that runs [block] when triggered.
 *
 * @param key An optional key to be used as a key for the action. If not provided we use the key
 * that is automatically generated by the Compose runtime which is unique for every exact code
 * location in the composition tree.
 * @param block the function to be run when this action is triggered.
 */
@Composable
fun action(
    key: String? = null,
    block: () -> Unit,
): Action {
    val finalKey = if (!key.isNullOrEmpty()) key else currentCompositeKeyHash.toString()
    return LambdaAction(finalKey, block)
}
```


# 更新ロジックがWorkManagerへ
これは試せてないのですが、リリースノートに興味深い文がありました。
>Moved GlanceAppWidget to a WorkManager session based update mechanism. Users of Glance for AppWidgets should now override GlanceAppWidget.provideGlance instead of the old Content method. As this now happens in a worker, this is now a good place to load resources, database or network items without having to have a separate worker.

>GlanceAppWidgetをWorkManagerのセッションベースの更新メカニズムに移行しました。Glance for AppWidgetsのユーザは、従来のContentメソッドではなく、GlanceAppWidget.provideGlanceをオーバーライドする必要があるようになりました。これはワーカーで起こるようになったので、別のワーカーを持つことなく、リソース、データベース、ネットワークアイテムをロードするのに適した場所となりました。(DeepL)

今までAPIコールをしたりデータベースを参照する場合、[Workerを起動する必要があった](https://speakerdeck.com/maiyama18/creating-kyash-widget?slide=27)のですが、その必要がなくなったのでしょうか
ここはもっと調査をする必要がありそうですね。