30 Mar 2025·7 dk okuma

Kotlin WorkManager ile saha uygulamaları için arka plan senkronizasyonu

Kotlin WorkManager ile saha uygulamaları için arka plan senkronizasyonu: doğru iş türünü seçin, kısıtlamalar belirleyin, üstel geri çekilme kullanın ve kullanıcıya görünür ilerleme gösterin.

Kotlin WorkManager ile saha uygulamaları için arka plan senkronizasyonu

Saha ve operasyon uygulamaları için güvenilir arka plan senkronizasyonu ne demektir

Saha ve operasyon uygulamalarında senkronizasyon “iyi olur” seçeneği değildir. Cihazdaki işin ekip için gerçek hale gelme yoludur. Senkronizasyon başarısız olunca kullanıcı hemen fark eder: tamamlanan iş hâlâ "beklemede" görünür, fotoğraflar kaybolur veya aynı rapor iki kez yüklenir ve çift kayıt oluşur.

Bu uygulamalar tipik tüketici uygulamalarından daha zordur çünkü telefonlar en kötü koşullarda çalışır. Ağ LTE, zayıf Wi‑Fi ve sinyalsiz arasında sürekli değişir. Pil tasarrufu arka plan işlerini engeller. Uygulama öldürülür, OS güncellenir ve cihazlar rota ortasında yeniden başlatılabilir. Güvenilir bir WorkManager kurulumu tüm bunların üstesinden drama olmadan gelmelidir.

Güvenilirlik genelde dört şeyi ifade eder:

  • Sonunda tutarlı: veri geç gelebilir ama elle gözetmeden ulaşır.
  • Kurtarılabilir: uygulama yükleme ortasında ölürse sonraki çalıştırma güvenli şekilde devam eder.
  • Gözlemlenebilir: kullanıcı ve destek ne olduğunu ve nerede takıldığını görebilir.
  • Tahrip edici değil: yeniden denemeler çoğaltma veya durum bozulmasına yol açmaz.

"Şimdi çalıştır" küçük, kullanıcı tetikli eylemler için uygundur (ör. kullanıcı işi kapatmadan önce tek bir durum güncellemesi göndermek). "Bekle" ise fotoğraf yüklemeleri, toplu güncellemeler veya zayıf ağ ve pil ihtimali olan ağır işler için uygundur.

Örnek: bir denetçi bodrum katında 12 fotoğraflı bir form gönderir. Güvenilir bir senkronizasyon her şeyi yerelde saklar, kuyrukta işaretler ve cihaz gerçek bağlantı olduğunda yeniden yükler; denetçi işi tekrar yapmak zorunda kalmaz.

Doğru WorkManager yapı taşlarını seçin

Başlamak için en küçük ve en net iş birimini seçin. Bu karar, daha sonra yapılacak herhangi bir akıllı yeniden deneme mantığından daha fazla güvenilirliği etkiler.

One-time vs periodic work

Yeni bir şey değişti diye olması gereken işler için OneTimeWorkRequest kullanın: yeni bir form kaydedildi, bir fotoğraf sıkıştırma işi bitti veya kullanıcı Sync'e dokundu. Hemen (kısıtlamalarla) enqueue edin ve WorkManager cihaz hazır olduğunda çalıştırsın.

Sabit bakım için, örneğin “güncellemeleri kontrol et” periyodik veya gece temizliği için PeriodicWorkRequest kullanın. Periyodik işler kesin zamanlı değildir. Minimum bir aralığı vardır ve pil ile sistem kurallarına göre kayma olabilir; bu yüzden önemli yüklemeler için tek yol olarak kullanılmamalıdır.

Pratik bir desen, "yakında eşitlenmeli" işler için one-time work ve güvenlik ağı olarak periyodik işleri kullanmaktır.

Worker, CoroutineWorker veya RxWorker seçimi

Kotlin yazıyor ve suspend fonksiyonları kullanıyorsanız CoroutineWorker tercih edin. Kod kısa kalır ve iptal beklediğiniz gibi çalışır.

Worker basit bloklayıcı kod için uygundur, ama çok uzun süre bloklamamaya dikkat etmelisiniz.

RxWorker sadece uygulamanız zaten RxJava'yı yoğun kullanıyorsa mantıklıdır; aksi halde ekstra karmaşıklıktır.

Adımları zincirlemek mi yoksa tek bir worker ile fazları mı çalıştırmak?

Adımları zincirlemek, adımlar bağımsız olarak başarılı ya da başarısız olabiliyorsa ve ayrı yeniden denemeler ve daha net loglar istiyorsanız harikadır. Fazlar halinde tek bir worker, adımlar veriyi paylaşıyorsa ve tek bir işlem gibi ele alınması gerekiyorsa daha iyidir.

Basit bir kural:

  • Adımlar farklı kısıtlamalara sahipse zincirleyin (ör. önce sadece Wi‑Fi ile yükleme, sonra hafif bir API çağrısı).
  • Tek bir "hepsi ya da hiçbiri" senkronizasyonu gerekiyorsa bir worker kullanın.

WorkManager işin kalıcılığını, süreç ölümü ve yeniden başlatmaları, ve kısıtlamalara uyumu garanti eder. Zamanlamada kesinlik, anında yürütme veya kullanıcı uygulamayı zorla durdurduktan sonra çalıştırma garantisi vermez. Bir Android saha uygulaması inşa ediyorsanız (AppMaster tarafından Kotlin olarak üretilmiş olsa bile), gecikmelerin güvenli ve beklenen olduğunu varsayacak şekilde senkronizasyon tasarlayın.

Senkronizasyonu güvenli hale getirin: idempotent, artımlı ve yeniden başlatılabilir

Bir saha uygulaması işi tekrar çalıştıracaktır. Telefonlar sinyal kaybeder, OS süreçleri öldürür ve kullanıcı hiçbir şey olmuyormuş gibi iki kez Sync'e basabilir. Arka plan senkronizasyonunuz tekrar çalıştırılmaya güvenli değilse çoğaltmalar, eksik güncellemeler veya sonsuz yeniden denemelerle karşılaşırsınız.

Her sunucu çağrısını iki kez çalıştırılsa bile güvenli olacak şekilde başlatın. En basit yaklaşım, öğe başına bir idempotency anahtarı (ör. yerel kayıtla saklanan UUID) kullanmaktır; sunucu aynı isteği aynı sonuç olarak ele alır. Sunucuyu değiştiremiyorsanız kararlı bir doğal anahtar ve upsert uç noktası veya sürüm numarası kullanın ki sunucu eski güncellemeleri reddedebilsin.

Worker tekrar çalıştırıldığında tahminde bulunmadan devam edebilmesi için yerel durumu açıkça izleyin. Basit bir durum makinesi genelde yeterlidir:

  • queued
  • uploading
  • uploaded
  • needs-review
  • failed-temporary

Senkronizasyonu artımlı tutun. "Her şeyi senkronize et" yerine lastSuccessfulTimestamp veya sunucudan alınan bir token gibi bir kursör saklayın. Küçük bir değişiklik sayfası okuyun, uygulayın ve kursörü yalnızca parti tamamen yerel olarak kaydedildikten sonra ilerletin. Küçük partiler (20–100 öğe gibi) zaman aşımını azaltır, ilerlemeyi görünür kılar ve kesinti sonrası tekrar edilecek işi sınırlar.

Fotoğraflar veya büyük yükler için yüklemeleri de yeniden başlatılabilir yapın. Dosya URI'sini ve yükleme meta verisini saklayın ve sunucu onayı olmadan öğeyi "uploaded" olarak işaretlemeyin. Worker yeniden başlarsa son bilinen durumdan devam etsin.

Örnek: bir teknisyen 12 form doldurur ve 8 fotoğraf ekler. Cihaz yeniden bağlandığında worker partiler halinde yükler, her form bir idempotency anahtarına sahiptir ve sync kursörü her parti başarıyla tamamlandıktan sonra ilerler. Uygulama yarıda kapanırsa, worker tekrar çalıştırıldığında kalan kuyruk öğelerini çoğaltmadan tamamlar.

Gerçek dünya cihaz koşullarına uygun kısıtlamalar

Kısıtlamalar, arka plan senkronizasyonunun pil tüketmesini, mobil veriyi boşa harcamasını veya en kötü zamanda başarısız olmasını engelleyen koruyuculardır. Kısıtlamaların cihazların sahadaki davranışını yansıtmasını isteğiniz; masanızdaki gibi değil.

Kullanıcıyı koruyan ama işi çoğu gün çalıştırmaya izin veren küçük bir kümeyle başlayın. Pratik bir temel: ağ bağlantısı gerektirin, pil düşükse çalıştırmayın ve depolama kritik derecede düşüksa çalıştırmayın. İş ağır ve zaman açısından hassas değilse sadece şarjda olmayı ekleyin; birçok saha cihazı vardiya sırasında nadiren prize takılıdır.

Aşırı kısıtlama "senkronizasyon hiç çalışmıyor" raporlarının yaygın nedenidir. Eğer "unmetered Wi‑Fi, şarjda ve pil düşük değil" gibi tüm koşulları istiyorsanız, neredeyse hiç çalışmayacak bir an bekliyorsunuz demektir. İş bugün gerektiriyorsa ideal koşulu beklemektense daha küçük işleri daha sık çalıştırmak genelde daha iyidir.

Captive portal'lar başka bir gerçek dünya sorunudur: telefon bağlı görünüyor, ama kullanıcı bir otel ya da halka açık Wi‑Fi sayfasında "Kabul Et"e dokunmalıdır. WorkManager bunu güvenilir şekilde tespit edemez. Buna normal bir hata gibi davranın: senkronizasyonu deneyin, hızlı zaman aşımı koyun ve daha sonra yeniden deneyin. İstek sırasında tespit edebiliyorsanız uygulama içinde "Wi‑Fi bağlı ama internet erişimi yok" gibi basit bir mesaj gösterin.

Küçük ve büyük yüklemeler için farklı kısıtlamalar kullanın:

  • Küçük yükler (durum pingleri, form meta verisi): herhangi bir ağ, pil düşük değil.
  • Büyük yükler (fotoğraflar, videolar, harita paketleri): mümkünse unmetered ağ ve şarj koşulunu düşünün.

Örnek: bir teknisyen 2 fotoğraflı bir form kaydeder. Form alanlarını her bağlantıda gönderin, ancak fotoğraf yüklemelerini Wi‑Fi veya daha uygun bir ana kadar kuyruklayın. Ofis işi hızlıca görür ve cihaz arka planda mobil veriyi boşa harcamaz.

Kullanıcıyı rahatsız etmeyen üstel geri çekilme (backoff) ile yeniden denemeler

Tüm yığın için tek bir platform
Backend, web uygulaması ve yerel mobil uygulamaları birlikte inşa edin, böylece modeller ve kimlik doğrulama uyumlu kalır.
Uygulama Oluştur

Yeniden denemeler saha uygulamalarını ya sakin ya da bozuk hissettiren yerlerdir. Beklenen hata tipine uygun bir backoff politikası seçin.

Ağlar için üstel geri çekilme genelde en güvenli varsayılandır. Kapsam kötü olduğunda sunucuyu veya pili yormamanız için bekleme süresini hızla artırır. Lineer backoff kısa geçici sorunlara uyar (ör. dalgalanan VPN) ama zayıf sinyal bölgelerinde çok sık yeniden denemeye yol açabilir.

Yeniden deneme kararlarını sadece "bir şey başarısız oldu"ya göre değil, hata tipine göre verin. Basit bir kural seti:

  • Ağ zaman aşımı, 5xx, DNS, bağlantı yok: Result.retry()
  • Auth süresi dolmuş (401): bir kez token yenileyin, sonra başarısız olup kullanıcıyı tekrar oturum açmaya yönlendirin
  • Doğrulama veya 4xx (bad request): Result.failure() ve destek için net bir hata
  • Çakışma (409) zaten gönderilmiş öğeler için: senkronizasyonunuz idempotent ise başarı sayın

Kalıcı bir hata sonsuza kadar döngüye girmesin diye zararları sınırlandırın. Maksimum deneme sayısı belirleyin; ondan sonra durun ve sessiz, eyleme geçirilebilir bir mesaj gösterin (sürekli bildirim değil).

Davranışı denemeler arttıkça değiştirebilirsiniz. Örneğin 2 hatadan sonra daha küçük partiler gönderin veya büyük yüklemeleri atlayın.

val request = OneTimeWorkRequestBuilder<SyncWorker>()
  .setBackoffCriteria(
    BackoffPolicy.EXPONENTIAL,
    30, TimeUnit.SECONDS
  )
  .build()

// in doWork()
if (runAttemptCount >= 5) return Result.failure()
return Result.retry()

Bu, yeniden denemeleri nazik tutar: daha az uyandırma, daha az kullanıcı müdahalesi ve bağlantı geri geldiğinde daha hızlı kurtarma.

Kullanıcıya görünür ilerleme: bildirimler, foreground çalışma ve durum

Demo değil, yerel uygulamalar gönderin
Çevrimdışı dostu veri akışları ve net senkronizasyon durumlarıyla yerel iOS ve Android uygulamaları oluşturun.
Mobil Oluştur

Saha uygulamaları genellikle kullanıcı beklemiyorken senkronize olur: bir bodrumda, yavaş ağda veya neredeyse boş pil ile. Senkronizasyon kullanıcının beklediği şeyi etkiliyorsa (yüklemeler, rapor gönderimleri, fotoğraf partileri), bunu görünür ve anlaşılır kılın. Küçük, hızlı güncellemeler için sessiz arka plan işi iyidir. Daha uzun işler dürüst hissettirmeli.

Ne zaman foreground gerekli

İş uzun sürüyorsa, zaman açısından kritikse veya açıkça bir kullanıcı eylemiyle ilişkiliyse foreground çalıştırma kullanın. Modern Android'de büyük yüklemeler foreground olarak çalıştırılmadıkça durdurulabilir veya ertelenebilir. WorkManager'da bu, ForegroundInfo döndürmek ve sistemin sürekli bir bildirim göstermesini sağlamak demektir.

İyi bir bildirim üç soruyu yanıtlar: ne senkronize oluyor, ne kadar ilerledi ve nasıl durdurulur. Kullanıcının metered veri kullanırken veya telefonuna hemen ihtiyaç duyduğunda işi iptal edebilmesi için net bir iptal eylemi ekleyin.

İnsanların güvenebileceği ilerleme

İlerleme soyut yüzdeler yerine gerçek birimlerle eşleşmelidir. setProgress ile ilerlemeyi güncelleyin ve UI'da WorkInfo üzerinden okuyun (veya bir durum ekranında). 12 fotoğraf ve 3 form yüklüyorsanız "15 öğeden 5'i yüklendi" gibi bildirin, kalanları gösterin ve son hata mesajını destek için saklayın.

İlerlemenin anlamlı kalması için:

  • Tamamlanan ve kalan öğe sayısı
  • Mevcut adım ("Fotoğraflar yükleniyor", "Formlar gönderiliyor", "Sonlandırılıyor")
  • Son başarılı senkron zamanı
  • Son hata (kısa, kullanıcı dostu)
  • Görünür iptal/durdurma seçeneği

Eğer AppMaster ile iç araçlarınızı hızlıca oluşturuyorsanız aynı kuralı uygulayın: kullanıcılar senkronizasyonu gördükçe güvenir ve bu senkronizasyon yaptıkları işlemlerle eşleşmelidir.

Unique work, etiketler ve çoğaltma işlerinden kaçınma

Çoğaltma işleri pil tüketir, mobil veriyi boşa harcar ve sunucu tarafında çakışmalara yol açar. WorkManager iki basit araç verir: unique work isimleri ve etiketler.

Varsayılan iyi yaklaşım “sync”i tek bir hat olarak ele almaktır. Uygulama her uyandığında yeni bir iş kuyruğa almak yerine aynı unique work adını kullanın. Böylece kullanıcı uygulamayı açtığında, ağ değiştiğinde ve periyodik iş aynı anda tetiklendiğinde bir sync fırtınası oluşmaz.

val request = OneTimeWorkRequestBuilder<SyncWorker>()
  .addTag("sync")
  .build()

WorkManager.getInstance(context)
  .enqueueUniqueWork("sync", ExistingWorkPolicy.KEEP, request)

Politika seçimi ana davranış tercihi:

  • KEEP: eğer bir sync zaten çalışıyorsa veya kuyrukta ise yeni isteği yoksayar. Çoğu "Sync now" butonu ve otomatik tetiklemeler için bunu kullanın.
  • REPLACE: mevcut olanı iptal edip yenisini başlatır. Hesap değişimi veya proje seçimi gibi girdi gerçekten değiştiyse bunu kullanın.

Etiketler kontrol ve görünürlük için elinizdeki arayüzdür. sync gibi sabit bir etiketle iş iptal edebilir, durum sorgulayabilir veya logları filtreleyebilirsiniz. Manuel "sync now" için zaten bir iş çalışıp çalışmadığını kontrol edip kullanıcıya net bir mesaj göstermek için çok faydalıdır.

Periyodik ve isteğe bağlı senkronizasyon birbirleriyle çatışmamalıdır. Ayrı ama koordine edilmiş tutun:

  • Zamanlanmış iş için enqueueUniquePeriodicWork("sync_periodic", KEEP, ...) kullanın.
  • İsteğe bağlı için enqueueUniqueWork("sync", KEEP, ...) kullanın.
  • Worker içinde yükleyecek bir şey yoksa hızlıca çıkın, böylece periyodik çalışma ucuz kalır.
  • İsteğe bağlı olarak, periyodik worker aynı one-time unique sync'i enqueue edebilir, böylece gerçek iş tek yerde toplanır.

Bu desenler arka plan senkronizasyonunu öngörülebilir kılar: aynı anda bir sync, kolay iptal ve kolay gözlem.

Adım adım: pratik bir arka plan senkronizasyon boru hattı

Küçük bir saha pilotu çalıştırın
Önce güvenilir bir dilimi yayınlayın, ör. bir denetim formu fotoğraflarla ve güvenli yeniden denemelerle.
Pilot Başlat

Güvenilir bir senkronizasyon boru hattı inşa etmek, işi önce yerelde tutmak ve WorkManager'ın yalnızca koşullar uygun olduğunda onları ilerletmesi gibi küçük bir durum makinesi gibi ele alındığında daha kolaydır.

Göndermeye hazır basit bir boru hattı

  1. Yerel "kuyruk" tablolarıyla başlayın. Devam ettirmek için gereken en küçük meta veriyi saklayın: öğe id'si, tür (form, fotoğraf, not), durum (pending, uploading, done), deneme sayısı, son hata ve indirmeler için bir kursör veya sunucu revizyonu.

  2. Kullanıcı tetiklediğinde "Sync now" için real dünya kısıtlamalarına uygun bir OneTimeWorkRequest enqueue edin. Yaygın seçimler: ağ bağlı ve pil düşük değil. Yükler ağırsa şarj gereksinimi ekleyin.

  3. Net fazları olan bir CoroutineWorker uygulayın: upload, download, reconcile. Her fazı artımlı tutun. Sadece pending olarak işaretlenmiş öğeleri yükleyin, sadece son kursörden itibaren değişiklikleri indirin ve sonra çatışmaları basit kurallarla çözün (ör. atama alanlarında sunucu kazanır, yerel taslak notlarda istemci kazanır).

  4. Geri çekilmeli yeniden denemeler ekleyin ama hangi hataların yeniden denenmesi gerektiğini seçici olun. Zaman aşımı ve 500'ler yeniden denenmeli. 401 (oturum kapalı) hızlı başarısız olmalı ve UI'ya ne olduğunu söylemeli.

  5. UI ve bildirimleri sürdürmek için WorkInfo'yu gözlemleyin. "10 öğeden 3'ü yükleniyor" gibi faz ilerlemeleri için progress güncellemeleri kullanın ve kısa bir hata mesajı gösterin ki sonraki adım (yeniden dene, giriş yap, Wi‑Fi'ye bağlan) belli olsun.

val constraints = Constraints.Builder()
  .setRequiredNetworkType(NetworkType.CONNECTED)
  .setRequiresBatteryNotLow(true)
  .build()

val request = OneTimeWorkRequestBuilder<SyncWorker>()
  .setConstraints(constraints)
  .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30, TimeUnit.SECONDS)
  .build()

Kuyruğu yerelde tuttuğunuzda ve worker fazlarını açık tuttuğunuzda, iş duraklayabilir, devam edebilir ve kullanıcıya ne olduğunu tahmin etmeden anlatabilir.

Yaygın hatalar ve tuzaklar (ve nasıl kaçınılır)

Güvenilir senkronizasyon çoğunlukla test sırasında zararsız görünen birkaç küçük seçim yüzünden gerçek cihazlarda başarısız olur. Amaç mümkün olduğunca sık çalıştırmak değil; doğru zamanda çalıştırmak, doğru işi yapmak ve yapamadığında temiz şekilde durmaktır.

Dikkat edilmesi gereken tuzaklar

  • Hiç kısıtlama olmadan büyük yüklemeler yapmak. Fotoğrafları herhangi bir ağda ve her pil seviyesinde gönderirseniz kullanıcı rahatsız olur. Ağ tipi ve düşük pil için kısıtlamalar ekleyin, büyük işleri küçük parçalara bölün.
  • Her hatada sonsuza kadar yeniden denemek. 401, süre dolmuş token veya eksik izin geçici değil kalıcı problemdir. Bunları sert hata olarak işaretleyin ve UI'ya net bir eylem gösterin (yeniden giriş). Sadece zaman aşımı gibi geçici sorunları yeniden deneyin.
  • Kazara çoğaltma oluşturmak. Worker iki kez çalışabilirse sunucu çift kayıt görür. Her öğe için istemci taraflı sabit bir ID kullanın ve sunucunun tekrarları yeni kayıt yerine güncelleme olarak ele almasını sağlayın.
  • Gerçek zamanlı ihtiyaçlar için periyodik iş kullanmak. Periyodik iş bakım içindir, anlık sync için one-time unique work kullanın.
  • “%100” gösterimini çok erken bildirmek. Yükleme tamamlanması, verinin kabul edilip uzlaştırılmasıyla aynı şey değildir. Aşamalarla takip edin ve sunucu onayı aldıktan sonra ancak tamamlandı gösterin.

Somut bir örnek: bir teknisyen zayıf sinyalde üç fotoğraflı bir form gönderir. Hiç kısıtlama olmadan başlatırsanız yüklemeler takılır, yeniden denemeler patlar ve uygulama yeniden başladığında form iki kez oluşturulabilir. Kullanılabilir bir ağa kısıtlayıp adımları bölerseniz ve her forma sabit bir ID atarsanız aynı senaryo tek, temiz bir sunucu kaydıyla ve doğru ilerleme mesajıyla sonuçlanır.

Göndermeden önce hızlı kontrol listesi

Yeniden yazmadan senkronizasyon mantığını test edin
Yükleme kuyruğunuzu, yeniden denemeleri ve ilerleme UX'ini görsel mantıkla yeniden yazmadan prototipleyin.
Şimdi Deneyin

Yayın öncesi senkronizasyonu gerçek saha kullanıcılarının yapacağı şekilde test edin: aralıklı sinyal, düşük pil ve çok sayıda dokunuş. En az bir yavaş cihaz ve bir yeni cihazda test edin. Log tutun ama kullanıcının UI'da ne gördüğüne de bakın.

  • Ağ yok, sonra geri gelme: Senkronizasyonu ağ kapalı başlatıp sonra açın. İşin kuyruklandığını ve tekrar çoğaltmadan devam ettiğini doğrulayın.
  • Cihaz yeniden başlatma: Senkron ortasında yeniden başlatın, sonra uygulamayı açın. İşin devam ettiğini veya yeniden planlandığını ve uygulamanın doğru durumu gösterdiğini doğrulayın.
  • Düşük pil ve düşük depolama: Pil tasarruf modu açın, düşük pil seviyesine düşürün ve depolamayı neredeyse dolu hale getirin. İşin uygun şekilde beklediğini ve koşullar iyileşince devam ettiğini doğrulayın.
  • Tekrarlayan tetiklemeler: "Sync" butonuna birkaç kez basın veya birden fazla ekrandan tetikleyin. Sonuçta bir mantıksal sync çalışması olmalı, paralel worker yığınları değil.
  • Sunucu hatalarını açıklanabilir kılma: 500, zaman aşımı ve auth hatalarını simüle edin. Yeniden denemelerin geri çekilmeli olduğunu, belirli bir sınırdan sonra durduğunu ve kullanıcıya "Sunucuya ulaşılamıyor, yeniden denenecek" gibi anlaşılır bir mesaj gösterildiğini kontrol edin.

Herhangi bir test uygulamayı belirsiz bırakıyorsa bunu hata olarak kabul edin. Kullanıcı yavaş senkronizasyonu affeder, veri kaybını veya ne olduğunu bilmemeyi affetmez.

Örnek senaryo: saha uygulamasında çevrimdışı formlar ve fotoğraf yüklemeleri

Operasyonlara net bir yönetim görünümü verin
Operasyon ekipleri için neyin senkronize olduğunu, neyin başarısız olduğunu ve nedenini görebilecekleri bir web yönetim paneli ekleyin.
Admin Oluştur

Bir teknisyen zayıf çekim olan bir sitede var. Çevrimdışıyken bir servis formu doldurur, 12 fotoğraf çeker ve Gönder'e basar. Uygulama önce her şeyi yerelde saklar (ör. local database): form için bir kayıt ve her fotoğraf için ayrı kayıtlar; durumlar PENDING, UPLOADING, DONE veya FAILED olur.

Gönderince uygulama benzersiz bir sync işi ekler ki iki kez basılsa çoğaltma olmasın. Yaygın bir kurulum, önce fotoğrafları yükleyen (daha büyük, daha yavaş) sonra eklemeler doğrulanınca form yükleyen WorkManager zinciridir.

Senkronizasyon gerçek hayata uygun koşullar sağlandığında çalışır: örneğin bağlı ağ, pil durumu ve depolama yeterliliği. Teknisyen bodrumdaysa ve sinyal yoksa arka planda pili yakıp durmak yerine hiçbir şey yapılmaz.

İlerleme açık ve kullanıcı dostudur. Yükleme foreground olarak çalışır ve "12'den 3 yükleniyor" gibi bir bildirim gösterir; net bir İptal eylemi vardır. İptal edilirse uygulama işi durdurur ve kalan öğeleri PENDING olarak bırakır; böylece daha sonra yeniden denemek veri kaybı olmadan mümkündür.

Flaky hotspot sonrası yeniden denemeler naziktir: ilk hata kısa sürede yeniden dener, ancak her hata sonrası bekleme giderek artar (üstel geri çekilme). İlk başta duyarlı hisseder, sonra pil ve ağı korumak için geri çekilir.

Operasyon ekibi için karşılık pratik: öğeler idempotent ve benzersiz şekilde kuyruğa alındığından daha az çift gönderim, hangi fotoğrafın neden başarısız olduğu ve ne zaman yeniden deneneceği gibi net hata durumları ve "gönderildi"nin gerçekten "güvenli şekilde saklandı ve senkronize edilecek" anlamına gelmesi.

Sonraki adımlar: önce güvenilirliği yayınlayın, sonra senkronizasyon kapsamını genişletin

Daha fazla senkronizasyon özelliği eklemeden önce "tamam" kelimesinin ne anlama geldiğini netleştirin. Çoğu saha uygulaması için bu "istek gönderildi" değil; "sunucu kabul etti ve onayladı"dır ve UI durumu gerçeği yansıtmalıdır. "Senkronize" yazan bir form uygulama yeniden başlatıldıktan sonra da öyle kalmalı; başarısız olan form bir sonraki adımı göstermelidir.

Kullanıcıların ve desteğin sorabileceği küçük bir set sinyal görünür yaparak uygulamayı güvenilir kılın:

  • Son başarılı senkron zamanı
  • Son senkron hatası (kısa mesaj)
  • Bekleyen öğeler (ör. 3 form, 12 fotoğraf)
  • Mevcut senkron durumu (Idle, Syncing, Needs attention)

Gözlemlenebilirliği özelliğin bir parçası olarak ele alın. Bu, sahada birinin zayıf bağlantıda ne olduğunu anlamasına saatler kazandırır.

Backend ve yönetim araçlarını da inşa ediyorsanız birlikte üretmek senkronizasyon sözleşmesini sabit tutmaya yardımcı olur. AppMaster (appmaster.io) üretim hazır bir backend, web admin paneli ve yerel mobil uygulamalar üretebilir; bu, modelleri ve kimliği hizalı tutup zor olan senkronizasyon kenarlarına odaklanmanızı sağlar.

Son olarak küçük bir pilot çalıştırın. Uçtan uca bir senkronizasyon parçası (ör. 1–2 fotoğraflı bir denetim formu) seçin ve kısıtlamalar, yeniden denemeler ve kullanıcıya görünür ilerlemeyle birlikte yayınlayın. O parça sıkıcı ve öngörülebilir hale geldiğinde, birer birer yeni özellik ekleyin.

SSS

Bir saha uygulamasında “güvenilir arka plan senkronizasyonu” aslında ne demektir?

Güvenilir arka plan senkronizasyonu, cihazda oluşturulan işin önce yerelde saklanması ve kullanıcı aynı adımları tekrar etmek zorunda kalmadan sonra yüklenmesini sağlar. Uygulama öldüğünde, yeniden başlatıldığında veya zayıf ağlarda bile veriyi kaybetmeden veya çoğaltma yaratmadan devam edebilmelidir.

Senkronizasyon için OneTimeWorkRequest mi yoksa PeriodicWorkRequest mi kullanmalıyım?

Bir olay tetiklenen her şey için OneTimeWorkRequest kullanın: “form kaydedildi”, “fotoğraf eklendi” veya kullanıcı Sync'e dokunduğunda. Periyodik bakım ve güvenlik ağı olarak PeriodicWorkRequest kullanın, ancak önemli yüklemeler için tek yol olarak güvenmeyin; periyodik işler zaman içinde kayabilir.

Hangi Worker türünü seçmeliyim: Worker, CoroutineWorker veya RxWorker?

CoroutineWorker, Kotlin ve suspend fonksiyonları kullanıyorsanız en basit ve en öngörülebilir tercihtir; iptal davranışı beklendiği gibi olur. Kısa, bloklayıcı işler için Worker kullanılabilir. Uygulama zaten RxJava etrafında kurulmuşsa RxWorker mantıklıdır, aksi takdirde ek karmaşıklıktır.

Birden fazla worker zinciri mi yapmalıyım yoksa tek bir worker içinde fazlar mı?

Adımlarda farklı kısıtlamalar veya ayrı yeniden denemeler istiyorsanız zincirleme (chaining) kullanın; örneğin önce Wi‑Fi ile büyük dosyaları yüklemek, sonra hafif bir API çağrısı yapmak. Tüm adımlar aynı veriyi paylaşıyor ve tek işlem gibi davranmalıysa, temiz fazları olan tek bir worker daha iyi olabilir.

Yeniden denemeler sunucuda çoğaltmalara nasıl yol açmasını engeller?

Her oluşturma/güncelleme isteğini iki kez çalıştırılsa aynı sonuca götürecek şekilde güvenli hale getirin. Basit yaklaşım, her öğe için bir idempotency anahtarı (ör. yerel kayıtta saklanan UUID) kullanmaktır. Sunucuyu değiştiremiyorsanız kararlı doğal anahtar ve upsert uç noktası veya sürüm numarası ile tekrarları engelleyin.

Uygulama senkronizasyon ortasında öldüğünde yüklemeleri nasıl kaldığı yerden devam ettiririm?

Yerel durumları açıkça saklayın: queued, uploading, uploaded, failed gibi. Sunucu onayını almadan öğeyi tamamlandı olarak işaretlemeyin. Dosya URI'si ve yükleme meta verisini kalıcı tutun, böylece worker yeniden başlasa en son bilinen durumdan devam eder.

Saha uygulaması senkronizasyon işleri için hangi kısıtlamalar iyi bir varsayılandır?

Kullanıcıları koruyup işin çoğu gün çalışmasını sağlayacak minimal kısıtlamalarla başlayın: ağ bağlantısı gereksinimi, düşük pil durumunda çalışmama ve kritik az depolama durumunda bekleme. unmetered veya charging gereklilikleri sahadaki cihazlarda senkronizasyonun hiç çalışmamasına neden olabilir, bu yüzden dikkatli kullanın.

Captive portal veya “Wi‑Fi var ama internet yok” durumunu uygulama nasıl ele almalı?

Wi‑Fi bağlı ama internet yoksa bunu normal bir hata gibi ele alın: isteği çabuk zaman aşımına uğratın, Result.retry() döndürün ve sonra yeniden deneyin. İstek sırasında tespit edebiliyorsanız kullanıcıya basit bir mesaj gösterin ki neden bağlı görünmesine rağmen senkronizasyon ilerlemiyor anlasın.

Değişken ağ koşulları için en güvenli yeniden deneme stratejisi nedir?

Zayıf ağlarda üstel (exponential) backoff en güvenli varsayılandır; bağlantı kötüken sunucuyu veya pili yormamanızı sağlar. Zaman aşımı ve 5xx hatalarını yeniden deneyin, kalıcı problemler (ör. 4xx) için hızlıca başarısız olun ve maksimum deneme sayısı koyun.

“Sync storm” oluşmasını nasıl önlerim ve kullanıcıya güvenilir ilerleme nasıl gösteririm?

Eş zamanlı çoklu tetiklemelerin paralel işler başlatmasını önlemek için senkronizasyonu unique work olarak koyun. Uzun süren veya kullanıcı tarafından başlatılan işler için foreground çalıştırma yapın ve gerçek sayıları gösteren bir bildirim ile net bir İptal seçeneği sunun.

Hızlı bir adım adım pratik arka plan senkronizasyon boru hattı nasıl olur?

Yerel kuyruk tabloları tutun: öğe id'si, türü, durum, deneme sayısı, son hata ve indirme için bir kursör veya sunucu revizyonu saklayın. Kullanıcı “Sync now” dediğinde uygun kısıtlamalarla OneTimeWorkRequest ekleyin. CoroutineWorker içinde fazları (upload, download, reconcile) net tutun ve her fazı küçük partilerle ilerletin. WorkInfo'yu gözlemleyerek UI ve bildirimleri yönetin.

Yaygın hatalar ve tuzaklar nelerdir (ve nasıl kaçınılır)?

Genel tuzaklar şunlardır:

  • Büyük yüklemeleri hiçbir kısıtlama olmadan çalıştırmak: fotoğrafları her ağda ve düşük pilde göndermek kullanıcıyı rahatsız eder. İşleri küçük parçalara bölün ve uygun kısıtlamalar koyun.
  • Her hatada sonsuza kadar yeniden denemek: 401 gibi kimlik hatalarını hızlıca gösterin ve kullanıcıyı yeniden oturum açmaya yönlendirin.
  • İstemeden çoğaltmalar yaratmak: her öğeye kalıcı bir istemci tarafı ID'si verin ve sunucunun tekrarları yeni kayıt yerine güncelleme olarak ele almasını sağlayın.
  • Periyodik işleri gerçek zamanlı ihtiyaçlar için kullanmak: periyodik iş bakım içindir, anlık “sync now” için one-time unique work kullanın.
  • “%100” durumunu erken bildirmek: sunucu onayını almadan tamamlandı demeyin; aşama aşama (queued, uploading, server confirmed) ilerleyin.

Bu hatalardan kaçınmak uygulamanın saha koşullarında güvenilir çalışmasını sağlar.

Yayın öncesi hızlı kontrol listesi nedir?

Gerçek saha kullanıcılarının yapacağı gibi test edin: kesik sinyal, düşük pil ve çok sayıda dokunuşla. En az bir eski cihaz ve bir yeni cihazda aşağıdakileri kontrol edin:

  • Ağ yokken başlatıp sonra geri gelince düzgün sıraya alınıp devam ediyor mu?
  • Senkron sırasında yeniden başlatma sonrası iş devam ediyor veya yeniden planlanıyor mu?
  • Düşük pil ve düşük depolamada iş beklemeli mi, sonra koşullar iyileşince devam ediyor mu?
  • “Sync” butonuna birkaç kez basmak bir mantıksal tek iş üretiyor mu?
  • 500, zaman aşımı, auth hatalarını simüle edip yeniden denemelerin kademeli ve sınırlı olduğunu, kullanıcıya anlaşılır mesaj gösterildiğini doğrulayın.

Eğer herhangi bir test uygulamayı belirsiz bir duruma bırakıyorsa bu bir hatadır.

Bir saha uygulamasında çevrimdışı formlar ve fotoğraf yüklemeleri senaryosu nasıl işler?

Teknisyen formu çevrimdışıyken doldurur, 12 fotoğraf çeker ve Gönder'e basar. Uygulama önce her şeyi yerelde saklar: bir form kaydı ve her fotoğraf için bir kayıt; durumlar PENDING, UPLOADING, DONE veya FAILED olur. Gönderince benzersiz bir sync işi eklenir, böylece iki kez basılsa bile çoğaltma olmaz. Fotoğrafları önce yükleyip eklemeler doğrulanınca form gönderme gibi bir zincir kullanılır. İş yalnızca gerçekçi koşullar sağlandığında (ağ, pil, depolama) çalışır. İlerleme bildirimi foreground çalışmasıyla “12'den 3 yükleniyor” gibi gösterilir ve İptal seçeneği varsa kalanlar PENDING olarak kalır. Yeniden denemeler üslup olarak kibar davranır: ilk hatada kısa, sonra giderek daha seyrek yeniden denemeler olur.

Bir sonraki adımlar olarak ne yapmalıyım?

Önce hangi işin “tamam” sayılacağına karar verin: çoğu durumda bu “istek gönderildi” değil, sunucunun kabul edip onaylamasıdır. UI şu sinyalleri tutarlı ve görünür kılın:

  • Son başarılı senkron zamanı
  • Son senkron hatası (kısa, kullanıcı dostu)
  • Bekleyen öğe sayısı (ör. 3 form, 12 fotoğraf)
  • Mevcut senkron durumu (Idle, Syncing, Needs attention)

Gözlemlenebilirlik özelliğin bir parçasıdır ve sahada büyük zaman kazandırır. Backend ve admin araçlarını birlikte geliştiriyorsanız, senkronizasyon sözleşmesini sabit tutmak kolaylaşır. AppMaster (appmaster.io) üretim hazır backend, web admin paneli ve yerel mobil uygulamalar üretebilir; bu, modeller ve kimlik doğrulama hizalamasını korurken karmaşık senkronizasyon kenarlarına odaklanmanızı sağlar.

Başlaması kolay
Harika bir şey yaratın

Ücretsiz planla AppMaster ile denemeler yapın.
Hazır olduğunuzda uygun aboneliği seçebilirsiniz.

Başlayın