إعادة فتح المتجر: تحميل البيانات إلى Android باستخدام coroutine

أوجه انتباهكم إلى ترجمة المقال الأصلي من مايك ناخيموفيتش


ذات مرة ، كنت أعمل في نيويورك تايمز وأنشأت مكتبة تسمى Store، وهي "مكتبة جافا لتحميل البيانات بسهولة وسرعة الاستجابة". لقد أنشأنا المتجر باستخدام RxJavaقوالب مأخوذة من تنفيذ ذاكرة التخزين المؤقت للجوافة . يتوقع مستخدمو التطبيق اليوم إجراء تحديثات للبيانات في واجهة المستخدم دون الحاجة إلى القيام بأشياء مثل السحب للتحديثلتحديث البيانات أو التنقل بين الشاشات ذهابًا وإيابًا. جعلتني الواجهة الأمامية التفاعلية من التفكير في كيفية الحصول على مستودعات بيانات تعريفية مع واجهات برمجة تطبيقات بسيطة تجرد الوظائف المعقدة مثل اختناق المهام المتعددة وتخزين القرص المؤقت ، وهي ضرورية في تطبيقات الهاتف المحمول الحديثة. في السنوات الثلاث من تشغيله ، يحتوي Store على 45 مساهمًا وأكثر من 3500 نجم GitHub. من الآن فصاعدًا ، يسعدني أن أعلن أن Dropbox ستستمر في التطوير النشط للمتجر وستقوم بإصداره بالكامل على Kotlin مع دعم Coroutinesو Flow. والآن Store 4، هذه فرصة للاستفادة مما تعلمناه من خلال إعادة التفكير في واجهة برمجة التطبيقات والاحتياجات الحالية لنظام Android البيئي.




Android . . , , Google. , Android. Android Jetpack:



, Android Jetpack :



https://developer.android.com/jetpack/docs/guide


  • :  , AndroidX , Lifecycle Scopes . , view- .
  • View Model Live Data:  , , ( , !).
  • Room:  SQLite, ORM RxJava .
  • Remote Data Source:  Jetpack, Retrofit Okhttp Square .

, , , ( , , Jetpack ;-) ). , . , Dropbox Store, , .


, Store, . ,


«… , , .  , , , ».

. , , , . , .


Store?


, , Store, Android- . — , . , UX. , , . , . Store, .


, , . …



Store :



Store


, , Store, , , .


4 – Android . , . , Room SQLDelight, , . -, push-, Firebase, «» . Store , , , , , . , Store: http://github.com/dropbox/Store.


Store 4 . RxJava , Flow.


, , , , RxJava? . , , . , . , , , , .


— . RxJava - . API RxJava :


// Observable.java
@CheckReturnValue
public final Disposable subscribe(Consumer onNext) {}

, , RxJava Observable Disposable . dispose(), . . RxJava2 @CheckReturnValue— , flowable.subscribe , . , , . , RxJava, .


RxJava , dispose(). . RxJava, , , Kotlin Flow , . , Flow . Flow , .


suspend fun Flow.collect(...)

Collect RxJava, , Flow. RxJava, collect() "suspend". , ( async/await), . Flow.collect , , .


, Android ( ) , , . , Kotlin, , viewModelScope Jetpack, , . , Android: , .


public fun CoroutineScope.launch(...)
 
viewModelScope.launch {
  flow.collect{ handle(it) }
}

, Flow. Android. , AndroidX . , ViewModel, , Room Flow. , (Paging). Store , Android , .


, Store , Android, , , , Kotlin multi-platform, . RxJava Kotlin native/js 6000 .


Store?


Store . Store, Fetcher, , , . , Store . Store Flow, — ! Store // , , .


Store


, Store. , :


StoreBuilder.fromNonFlow { api.fetchSubreddit(it, "10")}
            .persister(
              reader = db.postDao()::loadPosts,
              writer = db.postDao()::insertPosts,
              delete = db.postDao()::clearFeed)
            .cachePolicy(MemoryPolicy)
            .build()

:


  • ,
  • API , , .

Store  . persister() Store. , Observable, Jetpack Room, SQLDelight Realm.


:


Store



 Store  . , Flow, , ReturnType.


val store = StoreBuilder.from {
                articleId -> api.getArticle(articleId) //Flow<Article>
            }
            .build()

Store , , toString(), equals() hashCode(). Fetcher . . , equals() hashcode() data- Kotlin.


: Stream



API, Store, :


fun stream(request: StoreRequest<Key>):Flow<StoreResponse>Output>>

StoreRequest, , . StoreResponse. StoreResponse — Kotlin, Loading, Data Error. StoreResponse ResponseOrigin, , .



  • Loading ResponseOrigin. .
  • Data , , Store.
  • Error , , ResponseOrigin.

Store , StoreResponse.Error, Flow , , . - , render/updateUI . . :


lifecycleScope.launchWhenStarted {
  store.stream(StoreRequest.cached(key = key, refresh=true)).collect { response ->
    when(response) {
        is StoreResponse.Loading -> showLoadingSpinner()
        is StoreResponse.Data -> {
            if (response.origin == ResponseOrigin.Fetcher) hideLoadingSpinner()
            updateUI(response.value)
        }
        is StoreResponse.Error -> {
            if (response.origin == ResponseOrigin.Fetcher) hideLoadingSpinner()
            showError(response.error)
        }
    }
  }
}

: Store.get(key)Store.stream(key)  Store.fresh(key).


  • suspend fun Store.get(key: Key): Value
 — . , .
  • suspend fun Store.fresh(key: Key): Value
 — , .
  • suspend fun Store.stream(key: Key): Flow
 — (Flow) .

get():


lifecycleScope.launchWhenStarted {
  val article = store.get(key)
  updateUI(article)
}

store.get(key), ( ), . store.get(key) , . ( ) , . , , , Store. Store . Store , , .



 store.fresh(key)  ( ). ,  fresh()  ,  store.get()/stream()  .  fresh()  pull-to-refresh .
 fresh()  get()  .


Stream



, store.stream(key), , , / . stream() , .


lifecycleScope.launchWhenStarted { 
  store.stream(StoreRequest.cached(3, refresh = false)) 
.collect{ }
 
 
store.stream(StoreRequest.get(3)) // ,   
    .collect{  }




, Store . , , , . , . Store.get() 12 . , . .




 Store ,  persister()  . , , Store , , .



persister(),  Flow  Store  . , ,  Store,   Store.


, Observable (Jetpack Room, SQLDelight Realm), , , UX.


StoreBuilder.fromNonFlow {api.fetchSubreddit(it, "10")}
            .persister(
              reader = db.postDao()::loadPosts,
              writer = db.postDao()::insertPosts,
              delete = db.postDao()::clearFeed)
            .cachePolicy(MemoryPolicy)
            .build()

Store , . , Store (Realm, SQLite, Firebase ..). SQLite Room, Jetpack.


API Store — , . :


  • , Room
  • (StoreRequest)
  • (stream)
  • API, Kotlin.


, Store. , , Android, . , -, - . , , .


KotlinConf:





Store : github.com/dropbox/Store




, , Android Open Source Project, , Creative Commons 2.5 Attribution License


All Articles