Android Jetpack Tile抛出Java.util.concurrent.cancellation exception

发布于 2025-02-09 16:49:37 字数 2168 浏览 1 评论 0原文

我正在开发一个Android Wear Tile,偶尔会以此堆栈跟踪崩溃。

2022-06-22 15:19:24.753 24101-24101/myapp E/AndroidRuntime: FATAL EXCEPTION: main
    Process: myapp, PID: 24101
    java.util.concurrent.CancellationException
        at kotlinx.coroutines.guava.JobListenableFuture.getInternal(ListenableFuture.kt:438)
        at kotlinx.coroutines.guava.JobListenableFuture.get(ListenableFuture.kt:428)
        at androidx.wear.tiles.TileService$TileProviderWrapper.lambda$onTileRequest$0(TileService.java:234)
        at androidx.wear.tiles.TileService$TileProviderWrapper$$ExternalSyntheticLambda7.run(Unknown Source:4)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:246)
        at android.app.ActivityThread.main(ActivityThread.java:7690)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995)
     Caused by: kotlinx.coroutines.JobCancellationException: Job was cancelled; job=JobImpl{Cancelled}@d298571

我认为这是当我的瓷砖令人耳目一新的时候发生。我的瓷砖是使用Raturofit从REST API获取数据。该代码看起来像这样:

class WeatherTileService : TileService() {
    private val serviceScope = CoroutineScope(Dispatchers.IO)

    override fun onTileRequest(requestParams: TileRequest) = serviceScope.future {
        Log.d("Tile", "Refreshing weather data")
        val api = AmbientWeatherClient.getInstance()
        val devices = api.listUsersDevices(APP_KEY, API_KEY)
...
        Tile.Builder()
            .setResourcesVersion(RESOURCES_VERSION)
            .setFreshnessIntervalMillis(5 * 60 * 1000)
            .setTimeline(

interface AmbientWeatherAPI {

    @GET("devices")
    suspend fun listUsersDevices(
        @Query("applicationKey") applicationKey: String,
        @Query("apiKey") apiKey: String
    ): List<Device>

}

我不知道为什么会发生这种情况。有什么建议从哪里开始挖掘?

I am developing an Android Wear Tile and occasionally my app crashes with this stack trace.

2022-06-22 15:19:24.753 24101-24101/myapp E/AndroidRuntime: FATAL EXCEPTION: main
    Process: myapp, PID: 24101
    java.util.concurrent.CancellationException
        at kotlinx.coroutines.guava.JobListenableFuture.getInternal(ListenableFuture.kt:438)
        at kotlinx.coroutines.guava.JobListenableFuture.get(ListenableFuture.kt:428)
        at androidx.wear.tiles.TileService$TileProviderWrapper.lambda$onTileRequest$0(TileService.java:234)
        at androidx.wear.tiles.TileService$TileProviderWrapper$ExternalSyntheticLambda7.run(Unknown Source:4)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:246)
        at android.app.ActivityThread.main(ActivityThread.java:7690)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995)
     Caused by: kotlinx.coroutines.JobCancellationException: Job was cancelled; job=JobImpl{Cancelled}@d298571

I think this is occurring when my tile is refreshing. My tile is getting data from a REST API using Retrofit. The code looks something like this:

class WeatherTileService : TileService() {
    private val serviceScope = CoroutineScope(Dispatchers.IO)

    override fun onTileRequest(requestParams: TileRequest) = serviceScope.future {
        Log.d("Tile", "Refreshing weather data")
        val api = AmbientWeatherClient.getInstance()
        val devices = api.listUsersDevices(APP_KEY, API_KEY)
...
        Tile.Builder()
            .setResourcesVersion(RESOURCES_VERSION)
            .setFreshnessIntervalMillis(5 * 60 * 1000)
            .setTimeline(

interface AmbientWeatherAPI {

    @GET("devices")
    suspend fun listUsersDevices(
        @Query("applicationKey") applicationKey: String,
        @Query("apiKey") apiKey: String
    ): List<Device>

}

I cannot figure out why this is happening. Any suggestions where to start digging?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

嘿嘿嘿 2025-02-16 16:49:37

我感到惊讶的是,取消杀死了您的应用程序。但是您有一个10秒钟的窗口来完成该请求。我怀疑这是取消。

/**
 * Called when the system is requesting a new timeline from this Tile Service. The returned
 * future must complete after at most 10 seconds from the moment this method is called (exact
 * timeout length subject to change).
 *
 * <p>Note that this is called from your app's main thread, which is usually also the UI thread.
 *
 * @param requestParams Parameters about the request. See {@link TileRequest} for more info.
 */
@MainThread
@NonNull
protected abstract ListenableFuture<Tile> onTileRequest(@NonNull TileRequest requestParams);

我的建议将永远不会在NittilereQuest上进行任何可变长度工作,例如调用远程API。从缓存(例如房间数据库)提供服务通常更有意义。

同样,当瓷砖请求进来时可能无法使用网络。由于这个和许多其他原因,通常最好拥有一些背景过程更新数据,例如Workmanager。然后,这可以将更新发送给您的瓷砖,也可以将任何复杂性或应用本身发送。

I am surprised the cancellation kills your app. But you have a window of 10 seconds to complete that request. I suspect this is the cancellation.

/**
 * Called when the system is requesting a new timeline from this Tile Service. The returned
 * future must complete after at most 10 seconds from the moment this method is called (exact
 * timeout length subject to change).
 *
 * <p>Note that this is called from your app's main thread, which is usually also the UI thread.
 *
 * @param requestParams Parameters about the request. See {@link TileRequest} for more info.
 */
@MainThread
@NonNull
protected abstract ListenableFuture<Tile> onTileRequest(@NonNull TileRequest requestParams);

My advice would be never do any variable length work in onTileRequest, such as calling a remote API. It generally makes more sense to be serving this from a cache, such as a Room database.

Also the network may not be available when the tile request comes in. For this and many other reasons, it's typically better to have some background process updating data, such as WorkManager. This can then send an update to your Tile, but also any complications or the App itself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文