// 一个基于' userId '获取' User '对象并每30秒刷新一次的LiveData // as long as it is observed val userId : LiveData<String> = ... val user = userId.switchMap { id -> liveData { while(true) { // note that `while(true)` is fine because the `delay(30_000)` below will cooperate in // cancellation if LiveData is not actively observed anymore valdata = api.fetch(id) // errors are ignored for brevity emit(data) delay(30_000) } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// A retrying data fetcher with doubling back-off val user = liveData { var backOffTime = 1_000 var succeeded = false while(!succeeded) { try { emit(api.fetch(id)) succeeded = true } catch(ioError : IOException) { delay(backOffTime) backOffTime *= minOf(backOffTime * 2, 60_000) } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// a LiveData that tries to load the `User` from local cache first and then tries to fetch // from the server and also yields the updated value val user = liveData { // dispatch loading first emit(LOADING(id)) // check local storage val cached = cache.loadUser(id) if (cached != null) { emit(cached) } if (cached == null || cached.isStale()) { val fresh = api.fetch(id) // errors are ignored for brevity cache.save(fresh) emit(fresh) } }
1 2 3 4 5 6 7 8 9 10 11
// a LiveData that immediately receives a LiveData<User> from the database and yields it as a // source but also tries to back-fill the database from the server val user = liveData { val fromDb: LiveData<User> = roomDatabase.loadUser(id) emitSource(fromDb) val updated = api.fetch(id) // errors are ignored for brevity // Since we are using Room here, updating the database will update the `fromDb` LiveData // that was obtained above. See Room's documentation for more details. // https://developer.android.com/training/data-storage/room/accessing-data#query-observable roomDatabase.insert(updated) }