Çevrimdışı öncelikli bir uygulama geliştirme

Çevrimdışı öncelikli uygulama, tüm işlemleri veya kritik bir alt kümeyi gerçekleştirebilen bir uygulamadır internet erişimi olmadan da temel işlevini yerine getirebilecek. Yani, bir görevi iş mantığının bir kısmını veya tamamını çevrimdışı olarak yerine getirmesi gerekir.

Çevrimdışı öncelikli bir uygulama oluştururken göz önünde bulundurulması gereken noktalar veri katmanında başlar uygulama verilerine ve iş mantığına erişim sunar. Uygulamanın şunları yapması gerekebilir: Bu verileri zaman zaman cihazın dışındaki kaynaklardan yenileyebilirsiniz. İçinde Bu durumda, güncel kalmak için ağ kaynaklarını çağırması gerekebilir.

Ağ kullanılabilirliği her zaman garanti edilmez. Cihazların genellikle dönemleri veya yavaş ağ bağlantısı sorunundan kaynaklanır. Kullanıcılar aşağıdakilerle karşılaşabilir:

  • Sınırlı internet bant genişliği
  • Asansörde veya asansördeyken gibi geçiş bağlantı kesintileri yer alır.
  • Ara sıra veri erişimi. Örneğin, sadece kablosuz ağ kullanan tabletler.

Nedeni ne olursa olsun, uygulamaların düzgün çalışması genellikle mümkündür. nasıl yardımcı olabileceğini açıklayayım. Uygulamanızın çevrimdışıyken doğru bir şekilde çalıştığından emin olmak için şunları yapabilmesi gerekir:

  • Güvenilir bir ağ bağlantısı olmadan kullanılabilir durumda kalın.
  • İlk veriyi beklemek yerine kullanıcılara anında yerel veriler sunun. ağ çağrısının tamamlanması veya başarısız olması anlamına gelir.
  • Verileri, pil ve veri durumuna dikkat edecek şekilde getirin. Örneğin, Örneğin, yalnızca en uygun koşullarda (ör. şarj ederken veya kablosuz ağa bağlıyken.

Yukarıdaki ölçütleri karşılayabilen bir uygulamaya genellikle çevrimdışı öncelikli uygulama denir.

Çevrimdışı öncelikli bir uygulama tasarlayın

Çevrimdışı öncelikli bir uygulama tasarlarken veri katmanından başlamalı ve Uygulama verileri üzerinde gerçekleştirebileceğiniz iki ana işlem vardır:

  • Okumalar: Uygulamanın diğer bölümleri (ör. görüntüleme) tarafından kullanılmak üzere veri alma kullanıcıya gösterir.
  • Yazmalar: Kullanıcı girişi daha sonra almak üzere kalıcıdır.

Veri katmanındaki depolar, veri kaynaklarını birleştirmekten sorumludur uygulama verileri sağlamak için. Çevrimdışı öncelikli bir uygulamada en az bir veri olmalıdır en kritik görevlerini gerçekleştirmek için ağ erişimine ihtiyaç duymayan bir kaynaktır. Bir verileri okumaktır.

Çevrimdışı öncelikli bir uygulamada verileri modelleme

Çevrimdışı öncelikli bir uygulamanın, etkin durumdaki her depo için en az 2 veri kaynağı bulunur. ağ kaynaklarını kullanır:

  • Yerel veri kaynağı
  • Ağ veri kaynağı
ziyaret edin.
Çevrimdışı öncelikli veri katmanı, hem yerel hem de ağ veri kaynaklarından oluşur.
Şekil 1: Çevrimdışı öncelikli depo

Yerel veri kaynağı

Yerel veri kaynağı, uygulamanın standart veri kaynağıdır. Google uygulamanın daha üst katmanlarının okuduğu tüm verilerin tek kaynağı olmalıdır. Bu işlem, bağlantı durumları arasında veri tutarlılığı sağlar. Yerel veriler kaynağı genellikle diskte saklanan depolama alanı tarafından desteklenir. Yaygın olarak kullanılan bazı yöntemler en önemli nedenler şunlardır:

  • Room gibi ilişkisel veritabanları gibi yapılandırılmış veri kaynakları.
  • Yapılandırılmamış veri kaynakları. Örneğin, Datastore ile protokol arabellekleri buna örnek gösterilebilir.
  • Basit dosyalar

Ağ veri kaynağı

Ağ veri kaynağı, uygulamanın gerçek durumudur. Yerel veriler ağ veri kaynağıyla senkronize edilmiş olması gerekir. Ayrıca, görevin Bu durumda, uygulama tekrar internete bağlandığında güncellenmesi gerekir. Buna karşılık, ağ veri kaynağı yerel veri kaynağının gerisinde kalabilir ve Uygulama, bağlantı tekrar kurulduğunda bunu güncelleyebilir. Şuradaki alan adı ve kullanıcı arayüzü katmanları: Uygulama hiçbir zaman doğrudan ağ katmanıyla bağlantılı olmamalıdır. Uygulama, üçüncü tarafın sorumluluğundadır (repository) kendisi ile iletişim kurmak ve yerel veri kaynağını güncelleyin.

Kaynakların kullanıma sunulması

Yerel veri kaynakları ile ağ veri kaynakları, uygulamanızın okuma ve yazma olanağı sunar. Yerel bir veri kaynağını sorgulamak hızlı ve esnek olabilir. bazı örnekler anlatın. Öte yandan ağ veri kaynakları yavaş olabilir kısıtlıdır. Örneğin kimliğe göre RESTful kaynaklarına aşamalı olarak erişildiğinde. Kullanıcı genelde her veri kaynağı, kullandığı verileri temsil eder. sağlar. Bu nedenle, yerel veri kaynağı ve ağ veri kaynağı sahip olacaksınız.

Aşağıdaki dizin yapısı, bu kavramı görselleştirir. AuthorEntity, bir uygulamanın yerel veritabanından okunan bir yazarın temsili ve NetworkAuthor ağ üzerinden serileştirilmiş yetkili bir temsili:

data/
├─ local/
│ ├─ entities/
│ │ ├─ AuthorEntity
│ ├─ dao/
│ ├─ NiADatabase
├─ network/
│ ├─ NiANetwork
│ ├─ models/
│ │ ├─ NetworkAuthor
├─ model/
│ ├─ Author
├─ repository/

AuthorEntity ve NetworkAuthor ile ilgili ayrıntılar:

/**
 * Network representation of [Author]
 */
@Serializable
data class NetworkAuthor(
    val id: String,
    val name: String,
    val imageUrl: String,
    val twitter: String,
    val mediumPage: String,
    val bio: String,
)

/**
 * Defines an author for either an [EpisodeEntity] or [NewsResourceEntity].
 * It has a many-to-many relationship with both entities
 */
@Entity(tableName = "authors")
data class AuthorEntity(
    @PrimaryKey
    val id: String,
    val name: String,
    @ColumnInfo(name = "image_url")
    val imageUrl: String,
    @ColumnInfo(defaultValue = "")
    val twitter: String,
    @ColumnInfo(name = "medium_page", defaultValue = "")
    val mediumPage: String,
    @ColumnInfo(defaultValue = "")
    val bio: String,
)

Hem AuthorEntity hem de NetworkAuthor öğesini saklamak iyi bir uygulamadır. ve dış katmanların üçüncü bir türü açığa çıkarıyor. Böylece, tüketim. Bu, dış katmanların yerelleştirilmiş ve yerel bilgilerdeki ufak değişikliklerden Uygulama davranışını temelden değiştirmeyen ağ veri kaynakları. Bu, aşağıdaki snippet'te gösterilmektedir:

/**
 * External data layer representation of a "Now in Android" Author
 */
data class Author(
    val id: String,
    val name: String,
    val imageUrl: String,
    val twitter: String,
    val mediumPage: String,
    val bio: String,
)

Daha sonra ağ modeli, bunu yerel yapılandırmaya dönüştürmek için bir uzantı yöntemi tanımlayabilir. yerel modelde de benzer şekilde harici modele dönüştüren bir harici model bulunur. temsili aşağıdaki gibidir:

/**
 * Converts the network model to the local model for persisting
 * by the local data source
 */
fun NetworkAuthor.asEntity() = AuthorEntity(
    id = id,
    name = name,
    imageUrl = imageUrl,
    twitter = twitter,
    mediumPage = mediumPage,
    bio = bio,
)

/**
 * Converts the local model to the external model for use
 * by layers external to the data layer
 */
fun AuthorEntity.asExternalModel() = Author(
    id = id,
    name = name,
    imageUrl = imageUrl,
    twitter = twitter,
    mediumPage = mediumPage,
    bio = bio,
)

Okumalar

Okumalar, çevrimdışı öncelikli bir uygulamada uygulama verileri üzerinde gerçekleştirilen temel işlemdir. Siz Bu nedenle, uygulamanızın verileri okuyabilmesini ve yeni kullanıma sunulduğundan uygulamanın gösterebileceği veri bulunduğundan emin olun. Bunu yapabilen bir uygulama reaktif bir app'teki okuma API'lerini kullanabilir.

Aşağıdaki snippet'te OfflineFirstTopicRepository, tüm etiketler için Flows değerini döndürür okuma API'leri için de geçerli. Bu şekilde, güncelleme aldığında okuyucularını güncelleyebilir ağ veri kaynağından çıkarır. Başka bir deyişle, OfflineFirstTopicRepository aktarma işlemi, yerel veri kaynağı aşağıdaki durumlarda değişir: geçersiz kılındı. Dolayısıyla, OfflineFirstTopicRepository öğesinin her okuyucusu ağ bağlantısı sırasında tetiklenebilecek veri değişikliklerini işlemeye hazır uygulamaya geri yüklenir. Ayrıca, OfflineFirstTopicRepository verileri okur yerel veri kaynağından aktarmanızı sağlar. Yalnızca okuyucularını veri konusunda bilgilendirebilir önce yerel veri kaynağını güncelleyerek değişiklik gösterebilir.

class OfflineFirstTopicsRepository(
    private val topicDao: TopicDao,
    private val network: NiaNetworkDataSource,
) : TopicsRepository {

    override fun getTopicsStream(): Flow<List<Topic>> =
        topicDao.getTopicEntitiesStream()
            .map { it.map(TopicEntity::asExternalModel) }
}

Hata işleme stratejileri

Mevcut yazılımlara bağlı olarak, çevrimdışı öncelikli uygulamalardaki hataları ele almanın benzersiz yolları vardır: veri kaynaklarını bulun. Aşağıdaki alt bölümlerde bu durumlar, stratejileri.

Yerel veri kaynağı

Yerel veri kaynağından okuma sırasında oluşan hatalar nadiren meydana gelir. Koruma amaçlı hatalardan kaçınmak için Flows üzerinde catch operatörünü kullanın. okuyor.

catch operatörünün ViewModel içinde kullanımı aşağıdaki gibidir:

class AuthorViewModel(
    authorsRepository: AuthorsRepository,
    ...
) : ViewModel() {
   private val authorId: String = ...

   // Observe author information
    private val authorStream: Flow<Author> =
        authorsRepository.getAuthorStream(
            id = authorId
        )
        .catch { emit(Author.empty()) }
}

Ağ veri kaynağı

Bir ağ veri kaynağından veri okunurken hata oluşursa uygulamanın kullanarak verileri getirmeyi yeniden denemek üzere buluşsal bir yöntem kullanır. Yaygın buluşsal yöntemler şunlardır:

Üstel geri yükleme

Eksponansiyel geri yüklemede, uygulama başarılı olana kadar artan zaman aralıklarıyla ağ veri kaynağı veya diğer koşullar durmasını gerektirir.

Eksponansiyel geri yükleme ile veri okuma
Şekil 2: Eksponansiyel geri yükleme ile verileri okuma

Uygulamanın geri çekilmeye devam etmesinin gerekip gerekmediğini değerlendirecek kriterler şunlardır:

  • Ağ veri kaynağının gösterdiği hatanın türü. Örneğin, olmadığını gösteren bir hata döndüren ağ çağrılarını yeniden denemek yardımcı olur. Bunun aksine, HTTP isteklerinde ve gerekli kimlik bilgileri elde edilinceye kadar yetkilendirilir.
  • İzin verilen maksimum yeniden deneme sayısı.
Ağ bağlantısı izleme

Bu yaklaşımda okuma istekleri, uygulama bunu yapabileceğinden emin olana kadar sıraya alınır ağ veri kaynağına bağlanmalıdır. Bağlantı kurulduktan sonra okuma isteği daha sonra sıraya alınır, okunan veriler ve yerel veri kaynağı güncellenir. Android'de bu sıra, bir Room veritabanıyla tutulabilir ve sürekli çalışmanızı sağlar.

Ağ monitörleri ve sıralarla veri okuma
Şekil 3: Ağ izleme ile sıraları okuma

Yazma işlemleri

Çevrimdışı öncelikli uygulamalarda veri okumak için önerilen yöntem gözlemlenebilir türlerde ise yazma API'lerinin eşdeğeri, eşzamansız API'lerdir. askıya alma işlevleri olarak kabul edilir. Bu, kullanıcı arayüzü iş parçacığının engellenmesini önler ve hata Çevrimdışı öncelikli uygulamalarda yazma, bir ağdan geçildiğinde başarısız olabileceği için işleme belirleyebilirsiniz.

interface UserDataRepository {
    /**
     * Updates the bookmarked status for a news resource
     */
    suspend fun updateNewsResourceBookmark(newsResourceId: String, bookmarked: Boolean)
}

Yukarıdaki snippet'te tercih edilen eşzamansız API için Coroutines yöntemin askıya alınmasının önüne geçin.

Yazma stratejileri

Çevrimdışı öncelikli uygulamalara veri yazarken dikkate alınması gereken üç strateji vardır. Hangi seçeneği tercih edeceğiniz, yazılan verinin türüne ve dokunun:

Yalnızca online yazmalar

Verileri ağ sınırı dışına yazmaya çalışın. Başarılı olursa yerel veri kaynağına izin vermezseniz, aksi takdirde bir istisna atar ve yanıt verebilirler.

Yalnızca online yazmalar
Şekil 4: Yalnızca online yazmalar

Bu strateji genellikle Google Ads'de online olarak gerçekleşmesi gereken yazma işlemleri için neredeyse gerçek zamanlı olarak ayarlayabilirsiniz. Örneğin, banka havalesi. Yazma işlemleri başarısız olabileceğinden, kullanıcıya yazmanın başarısız olduğunu bildirmek veya kullanıcının çalışmasını önlemek veri yazmaya çalışmayın. Kullanabileceğiniz bazı stratejiler bu senaryolarda şunlar bulunabilir:

  • Bir uygulama, veri yazmak için internet erişimi gerektiriyorsa ekran gösterilmeyebilir kullanıcıya veri yazmasına olanak tanıyan bir kullanıcı arayüzü veya en azından devre dışı bırakır.
  • Kullanıcının kapatamayacağı bir pop-up mesaj veya geçici bir istem kullanabilirsiniz. (kullanıcıya çevrimdışı olduğunu bildirmek için)

Kuyruğa alınan yazmalar

Yazmak istediğiniz bir nesne olduğunda onu sıraya ekleyin. Devam uygulama tekrar çevrimiçi olduğunda üstel şekilde kapatılarak sıranın hızlı bir şekilde tüketilmesine olanak tanır. Şu tarihte: Android, çevrimdışı bir sırayı boşaltmak genellikle yetkili WorkManager.

Yeniden denemelerle sıraları yazma
Şekil 5: Yeniden denemelerle sıraları yazma

Aşağıdaki durumlarda bu yaklaşım iyi bir seçenektir:

  • Verilerin hiçbir zaman ağa yazılması zorunlu değildir.
  • İşlemin zamana duyarlı olmaması gerekir.
  • İşlem başarısız olursa kullanıcının bilgilendirilmesi gerekli değildir.

Bu yaklaşımın kullanım alanları arasında analiz etkinlikleri ve günlük kaydı bulunur.

Tembel yazmalar

Önce yerel veri kaynağına yazın, ardından ağı bilgilendirmek için yazma işlemini sıraya koyun iletmenizi rica ediyoruz. Çatışmalar olabileceğinden bu basit bir soru değildir uygulama tekrar çevrimiçi olduğunda ağ ile yerel veri kaynakları arasında bağlantı kurar. İlgili içeriği oluşturmak için kullanılan çatışma çözümüyle ilgili bir sonraki bölümde daha fazla ayrıntı bulabilirsiniz.

Ağ izleme ile geç yazma
Şekil 6: Geç yazma işlemleri

Veriler uygulama için kritik olduğunda bu yaklaşım doğru bir seçimdir. Örneğin, Örneğin, çevrimdışı öncelikli yapılacaklar listesi uygulamasında, Kullanıcı çevrimdışı veriler, veri kaybı riskini önlemek için yerel olarak depolanır.

Senkronizasyon ve çakışma çözümü

Çevrimdışı öncelikli bir uygulama bağlantısını yeniden sağladığında, verileri ile ağ veri kaynağındaki verileri kullanır. Bu işlem senkronizasyon olarak adlandırılır. Bir uygulama iki şekilde senkronize edilebilir: (Ağ veri kaynağıyla):

  • Getirme tabanlı senkronizasyon
  • Push tabanlı senkronizasyon

Getirme tabanlı senkronizasyon

Çekme tabanlı senkronizasyonda, uygulama uygulama verileri sunar. Bu yaklaşım için yaygın buluşsal yaklaşımlardan biri gezinme temelli bir yöntemle, uygulama yalnızca verileri kullanıcılara sunmadan hemen önce getirir. gösterir.

Bu yaklaşım, uygulamanın kısa ila ara dönemler beklediği durumlarda en iyi sonucu verir. Ağ bağlantısı yok. Bunun nedeni, veri yenilemenin fırsata dayalı olması ve uzun devre dışı kaldığında, kullanıcının işlemi tekrarlama Eski veya boş önbelleğine sahip uygulama hedeflerini ziyaret etme.

Getirme tabanlı senkronizasyon
Şekil 7: Çekmeye dayalı senkronizasyon: A cihazı, A ve B ekranlarının kaynaklarına erişir B cihazı yalnızca B, C ve D ekranlarının kaynaklarına erişirken

Sonsuz bir şekilde öğeleri getirmek için sayfa jetonlarının kullanıldığı bir uygulama düşünün kaydırma listesini kullanabilirsiniz. Uygulama işlemi, verileri yerel veri kaynağında saklamayı ve ardından kullanıcıya bilgi sunmak için yerel veri kaynağı. Projenin gidişatı boyunca ağ bağlantısı yoksa depo, yerel ağ bağlantısından veri isteyebilir veri kaynağı değildir. Bu, Jetpack Paging Kitaplığı tarafından kullanılan kalıptır kendi RemoteMediator API'sini kullanın.

class FeedRepository(...) {

    fun feedPagingSource(): PagingSource<FeedItem> { ... }
}

class FeedViewModel(
    private val repository: FeedRepository
) : ViewModel() {
    private val pager = Pager(
        config = PagingConfig(
            pageSize = NETWORK_PAGE_SIZE,
            enablePlaceholders = false
        ),
        remoteMediator = FeedRemoteMediator(...),
        pagingSourceFactory = feedRepository::feedPagingSource
    )

    val feedPagingData = pager.flow
}

Çekme tabanlı senkronizasyonun avantajları ve dezavantajları aşağıdaki tabloda görebilirsiniz:

Avantajları Dezavantajları
Uygulaması nispeten kolaydır. Yoğun veri kullanımına açıktır. Bunun nedeni, gezinme hedefine yapılan yinelenen ziyaretlerin, değiştirilmeyen bilgilerin gereksiz şekilde yeniden getirilmesini tetiklemesidir. Uygun önbelleğe alma işlemiyle bu sorunu önleyebilirsiniz. Bu işlem, kullanıcı arayüzü katmanında cachedIn operatörüyle veya ağ katmanında HTTP önbelleğiyle yapılabilir.
Gereksiz veriler hiçbir zaman getirilmez. Alınan modelin kendi kendine yeterli olması gerektiğinden ilişkisel verilerle iyi ölçeklenmez. Senkronize edilmekte olan model, kendisinin doldurulması için getirilecek diğer modellere bağlıysa daha önce bahsedilen yoğun veri kullanımı sorunu daha da önemli hale getirilecektir. Ayrıca, üst modelin depoları ile iç içe yerleştirilmiş modelin depoları arasında bağımlılıklara neden olabilir.

Push tabanlı senkronizasyon

Push tabanlı senkronizasyonda, yerel veri kaynağı bir replikayı taklit etmeye çalışır. ağ veri kaynağı kümesini mümkün olan en iyi şekilde çalışır. Proaktif bir şekilde bir referans ayarlamak için ilk başlatmada uygun miktarda veri getirirse Bu veriler, sağlandığında bunu uyarmak için sunucudan gelen bildirimlere güvenir. eskidir.

Push tabanlı senkronizasyon
Şekil 8: Push tabanlı senkronizasyon: Veri değiştiğinde ağ, uygulamayı bilgilendirir ve Uygulama, değiştirilen verileri getirerek yanıt veriyor

Eski bildirimi aldıktan sonra uygulama, ağ ile iletişime geçerek eski olarak işaretlenen verileri güncelleyebilir. Bu çalışma, Ağ veri kaynağına ulaşan ve verileri saklayan Repository yerel veri kaynağına getirilir. Depo, verilerini 2008'den bu yana okuyuculara herhangi bir değişiklik olması durumunda bildirim gönderilir.

class UserDataRepository(...) {

    suspend fun synchronize() {
        val userData = networkDataSource.fetchUserData()
        localDataSource.saveUserData(userData)
    }
}

Bu yaklaşımda uygulama, ağ veri kaynağına çok daha az bağımlıdır. uzun süre boyunca çalışmayacaktır. Hem okuma hem de yazma çünkü en güncel bilgilere sahip olduğu varsayıldığından çevrimdışıyken de yerel olarak ağ veri kaynağından kaldırın.

Push tabanlı senkronizasyonun avantajları ve dezavantajları aşağıdaki tabloda görebilirsiniz:

Avantajları Dezavantajları
Uygulama süresiz olarak çevrimdışı kalabilir. Çakışmaların çözümü için sürüm oluşturma verileri önem taşımaz.
Minimum veri kullanımı. Uygulama yalnızca değişen verileri getirir. Senkronizasyon sırasında yazma ile ilgili sorunları dikkate almanız gerekir.
İlişkisel verilerde iyi performans gösterir. Her depo yalnızca desteklediği model için veri getirmekten sorumludur. Ağ veri kaynağının senkronizasyonu desteklemesi gerekir.

Karma senkronizasyon

Bazı uygulamalar, çalışma düzenine bağlı olarak çekme veya aktarma dışı verilerdir. Örneğin bir sosyal medya uygulaması, Feed'in yüksek sıklığı nedeniyle kullanıcının aşağıdaki seç-izle feed'ini getir güncellemelerine göz atın. Aynı uygulama, aşağıdaki koşullarla ilgili veriler için push tabanlı senkronizasyon kullanmayı da oturum açmış kullanıcıyı (kullanıcı adı, profil resmi vb.)

Sonuç olarak, çevrimdışı öncelikli senkronizasyon seçimi ürün gereksinimlerine bağlıdır ve mevcut teknik altyapıdır.

Çatışma çözümü

Uygulama çevrimdışıyken ağla uyumlu olmayan yerel olarak veri yazıyorsa veri kaynağı üzerinde, daha önce çözmeniz gereken bir çakışma gerçekleşmesine neden olabilir.

Çakışma çözümü, genellikle sürüm oluşturmayı gerektirir. Uygulamanın bazı işlemleri yapması gerekir değişikliklerin ne zaman gerçekleştiğini izlemek için muhasebe kaydırma araçlarını kullanabilirsiniz. Bu, reklamların meta verileri ağ veri kaynağına ekleyin. Ağ veri kaynağı, Mutlak doğru kaynağı sağlama sorumluluğudur. Farklı ürünler için tarafların ihtiyaçlarına bağlı olarak, çatışmaların çözümü için bir uygulamadır. Mobil uygulamalar için genel yaklaşım "son yazma kazanır"dır.

Son yazma işlemi kazanır

Bu yaklaşımda cihazlar, yazdıkları verilere zaman damgası meta verileri ekler. ağa katılmaz. Ağ veri kaynağı bunları aldığında tüm verileri siler mevcut durumundan daha eski olanları kabul ederken, mevcut durumdan daha yeni olanları kabul eder.

Son yazma, anlaşmazlık çözümünü kazanır
Şekil 9: "Son yazma kazanır" Verilerin doğru kaynağı, veri yazma

Yukarıda her iki cihaz da çevrimdışı ve başlangıçta ağ veri kaynağına ekleyin. Çevrimdışıyken hem yerel olarak veri yazarlar hem de takip ederler yüzde 10 oranında artış oldu. İkisi de internete tekrar girip veri kaynağıyla senkronize edildiğinde, ağ çakışmayı verilerini daha sonra yazdığı için B cihazındaki kalıcı veriler.

Çevrimdışı öncelikli uygulamalarda WorkManager

Yukarıda ele alınan hem okuma hem de yazma stratejilerinde, iki yaygın senaryo vardı yardımcı programlar:

  • Sıralar
    • Okumalar: Ağ bağlantısı kullanıma sunulana kadar okumaları ertelemek için kullanılır.
    • Yazma: Ağ bağlantısı kurulana kadar yazmaları ertelemek için kullanılır tekrar denenmesi için yazmaları yeniden sıraya sokmak önemlidir.
  • Ağ bağlantısı monitörleri
    • Okuma: Uygulama etkinken okuma sırasını boşaltmak için sinyal olarak kullanılır bağlı ve senkronizasyon için
    • Yazma: Uygulama etkinken yazma sırasını boşaltmak için sinyal olarak kullanılır bağlı ve senkronizasyon için

Her iki durum da WorkManager kalıcı çalışma örnekleridir. konusunda uzmanlaşmıştır. Örneğin, Now in Android örnek uygulamasında WorkManager, senkronizasyon işlemi sırasında hem okuma sırası hem de ağ izleyici olarak kullanılır yerel veri kaynağı. Başlangıçta uygulama aşağıdaki işlemleri gerçekleştirir:

  1. Okuma senkronizasyonu işi arasında denklik olduğundan emin olmak için yerel veri kaynağı ve ağ veri kaynağı.
  2. Okuma senkronizasyonu sırasını boşalt ve uygulama etkinken senkronizasyonu başlat çevrimiçi.
  3. Eksponansiyel geri yükleme kullanarak ağ veri kaynağından okuma işlemi gerçekleştirin.
  4. Okumanın sonuçlarını yerel veri kaynağına ekleyerek bir toplantıdır.
  5. Uygulamanın diğer katmanları için yerel veri kaynağındaki verileri kullanıma sunun tüketim.

Yukarıdaki şema, aşağıdaki şemada gösterilmektedir:

Now in Android uygulamasında veri senkronizasyonu
Şekil 10: Now in Android uygulamasında veri senkronizasyonu

Senkronizasyon işleminin WorkManager ile sıraya konulması işlemi, aşağıdaki şekilde yapılır: KEEP ExistingWorkPolicy ile benzersiz çalışma olarak belirtmek için:

class SyncInitializer : Initializer<Sync> {
   override fun create(context: Context): Sync {
       WorkManager.getInstance(context).apply {
           // Queue sync on app startup and ensure only one
           // sync worker runs at any time
           enqueueUniqueWork(
               SyncWorkName,
               ExistingWorkPolicy.KEEP,
               SyncWorker.startUpSyncWork()
           )
       }
       return Sync
   }
}

Burada SyncWorker.startupSyncWork() aşağıdaki şekilde tanımlanır:


/**
 Create a WorkRequest to call the SyncWorker using a DelegatingWorker.
 This allows for dependency injection into the SyncWorker in a different
 module than the app module without having to create a custom WorkManager
 configuration.
*/
fun startUpSyncWork() = OneTimeWorkRequestBuilder<DelegatingWorker>()
    // Run sync as expedited work if the app is able to.
    // If not, it runs as regular work.
   .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
   .setConstraints(SyncConstraints)
    // Delegate to the SyncWorker.
   .setInputData(SyncWorker::class.delegatedData())
   .build()

val SyncConstraints
   get() = Constraints.Builder()
       .setRequiredNetworkType(NetworkType.CONNECTED)
       .build()

Özellikle, SyncConstraints tarafından tanımlanan Constraints için şunlar gerekir: NetworkType, NetworkType.CONNECTED olmalıdır. Yani, o ana kadar kullanılabilir hale gelir.

Ağ kullanılabilir olduğunda Çalışan benzersiz iş sırasını boşaltır. SyncWorkName tarafından belirlenen ilgili Repository sağlar. Senkronizasyon başarısız olursa doWork() yöntemi Result.retry(). WorkManager, şununla senkronizasyonu otomatik olarak yeniden dener: eksponansiyel geri yükleme Aksi takdirde, tamamlanan Result.success() değerini döndürür senkronize edilir.

class SyncWorker(...) : CoroutineWorker(appContext, workerParams), Synchronizer {

    override suspend fun doWork(): Result = withContext(ioDispatcher) {
        // First sync the repositories in parallel
        val syncedSuccessfully = awaitAll(
            async { topicRepository.sync() },
            async { authorsRepository.sync() },
            async { newsRepository.sync() },
        ).all { it }

        if (syncedSuccessfully) Result.success()
        else Result.retry()
    }
}

Örnekler

Aşağıdaki Google örneklerinde çevrimdışı öncelikli uygulamalar gösterilmektedir. Uygulamadaki bu rehberliği görmek için bu yöntemleri inceleyin:

ziyaret edin.