Synchronizacja w tle aplikacji mobilnej offline-first: konflikty, ponawianie, UX
Zaplanuj synchronizację w tle w aplikacjach mobilnych offline-first z jasnymi regułami konfliktów, logiką ponawiania i prostym UX dla oczekujących zmian w natywnych aplikacjach Kotlin i SwiftUI.

Problem: użytkownicy edytują offline, a rzeczywistość się zmienia
Ktoś zaczyna zadanie przy dobrej sieci, potem wchodzi do windy, do kąta magazynu lub tunelu metra. Aplikacja dalej działa, więc użytkownik pracuje dalej. Naciska Zapisz, dodaje notatkę, zmienia status, może nawet tworzy nowy rekord. Na ekranie wszystko wygląda OK, bo widok aktualizuje się od razu.
Później łącze wraca i aplikacja próbuje nadrobić zaległości w tle. To właśnie tu synchronizacja w tle potrafi zaskoczyć.
Jeśli aplikacja nie jest ostrożna, ta sama akcja może zostać wysłana dwa razy (duplikaty), albo nowsza zmiana na serwerze może nadpisać to, co użytkownik właśnie zrobił (utrata edycji). Czasem aplikacja pokazuje mylące stany typu „Zapisano” i „Nie zapisano” jednocześnie, albo rekord pojawia się, znika i pojawia się ponownie po synchronizacji.
Konflikt to prosta sytuacja: dwie różne zmiany dotyczyły tego samego obiektu, zanim aplikacja miała szansę je pogodzić. Przykład: agent wsparcia ustawia priorytet zgłoszenia na Wysoki będąc offline, a współpracownik online zamyka zgłoszenie. Kiedy telefon offline się połączy, obie zmiany nie mogą zostać zastosowane bez reguły.
Celem nie jest sprawić, by offline wyglądało idealnie. Celem jest uczynić to przewidywalnym:
- Ludzie mogą pracować dalej bez obawy o utratę pracy.
- Synchronizacja odbywa się później bez tajemniczych duplikatów.
- Gdy coś wymaga uwagi, aplikacja wyraźnie mówi, co się stało i co robić dalej.
To prawda zarówno jeśli kodujesz ręcznie w Kotlin/SwiftUI, jak i gdy budujesz natywne aplikacje na platformie no-code takiej jak AppMaster. Trudniejsze nie są widgety UI. Trudniejsze jest zdecydowanie, jak aplikacja ma się zachować, gdy świat się zmieni, podczas gdy użytkownik był offline.
Prosty model offline-first (bez żargonu)
Aplikacja offline-first zakłada, że telefon czasem straci sieć, ale aplikacja powinna nadal być użyteczna. Ekrany powinny się ładować, a przyciski działać nawet jeśli serwer nie jest osiągalny.
Cztery pojęcia wystarczą w większości przypadków:
- Lokalny cache: dane przechowywane na urządzeniu, dzięki czemu aplikacja pokazuje coś natychmiast.
- Kolejka synchronizacji: lista akcji wykonanych przez użytkownika offline (lub przy niestabilnym łączu).
- Prawda serwera: wersja przechowywana na backendzie, którą wszyscy ostatecznie dzielą.
- Konflikt: kiedy zmiana z kolejki nie da się zastosować, bo wersja na serwerze się zmieniła.
Przydatny model myślowy to oddzielenie odczytów od zapisów.
Odczyty zwykle są proste: pokaż najlepsze dostępne dane (często z lokalnego cache), a potem cicho odśwież, gdy sieć wróci.
Zapisy są inne. Nie polegaj na „zapisaniu całego rekordu” za jednym razem. To zawodzi, gdy jesteś offline.
Zamiast tego zapisuj, co użytkownik zrobił, jako małe wpisy w dzienniku zmian. Na przykład: „ustawiono status na Zatwierdzony”, „dodano komentarz X”, „zmieniono ilość z 2 na 3”. Każdy wpis trafia do kolejki synchronizacji z timestampem i ID. Synchronizacja w tle potem próbuje to dostarczyć.
Użytkownik pracuje dalej, podczas gdy zmiany przechodzą od stanu oczekującego do zsynchronizowanego.
Jeśli używasz platformy no-code takiej jak AppMaster, nadal chcesz tych samych elementów: cache do szybkich ekranów i czytelną kolejkę akcji użytkownika, którą można ponawiać, łączyć lub oznaczać przy konflikcie.
Zdecyduj, co naprawdę wymaga wsparcia offline
Offline-first może brzmieć jak „wszystko działa bez połączenia”, ale obietnica ta jest tym, gdzie wiele aplikacji ma problemy. Wybierz części, które rzeczywiście zyskują na wsparciu offline, a resztę zostaw wyraźnie jako online-only.
Myśl w kategoriach intencji użytkownika: co ludzie muszą zrobić w piwnicy, w samolocie lub w magazynie z przerywaną łącznością? Dobrym domyślnym wyborem jest wspieranie akcji, które tworzą lub aktualizują codzienną pracę, a blokowanie akcji tam, gdzie liczy się „najnowsza prawda”.
Zestaw praktycznych offline-friendly akcji często obejmuje tworzenie i edycję kluczowych rekordów (notatki, zadania, inspekcje, zgłoszenia), tworzenie szkiców komentarzy i dołączanie zdjęć (przechowywanych lokalnie, wysyłanych później). Usuwanie też może działać, ale bezpieczniej jako miękkie usunięcie z oknem cofnięcia do momentu potwierdzenia przez serwer.
Następnie zdecyduj, co musi pozostać w czasie rzeczywistym, bo ryzyko jest zbyt duże. Płatności, zmiany uprawnień, zatwierdzenia i wszystko związane z wrażliwymi danymi zwykle powinno wymagać połączenia. Jeśli użytkownik nie może potwierdzić ważności akcji bez sprawdzenia serwera, nie zezwalaj na nią offline. Wyświetl jasny komunikat „wymagane połączenie”, a nie tajemniczy błąd.
Ustal oczekiwania co do świeżości danych. „Offline” nie jest binarne. Określ, jak przestarzałe mogą być dane: minuty, godziny, czy „następne otwarcie aplikacji”. Umieść tę regułę w UI prostymi słowami, np. „Ostatnia aktualizacja: 2 godziny temu” oraz „Synchronizacja po połączeniu”.
Na koniec wczesne oznacz dane narażone na konflikty. Stany magazynowe, współdzielone zadania i wiadomości zespołowe szybko przyciągają konflikty, bo wiele osób je szybko edytuje. Dla nich rozważ ograniczenie edycji offline do szkiców lub rejestrowanie zmian jako oddzielnych zdarzeń zamiast nadpisywania pojedynczej wartości.
Jeśli budujesz w AppMaster, ten krok decyzji pomaga Ci zamodelować dane i reguły biznesowe, tak by aplikacja przechowywała bezpieczne szkice offline, a ryzykowne akcje pozostawić online.
Zaprojektuj kolejkę synchronizacji: co przechowujesz dla każdej zmiany
Gdy użytkownik pracuje offline, nie próbuj „zsynchronizować bazy danych”. Synchronizuj akcje użytkownika. Jasna kolejka akcji to kręgosłup synchronizacji w tle i jest czytelna, gdy coś pójdzie nie tak.
Zachowaj akcje małe i ludzkie, zgodne z tym, co faktycznie zrobił użytkownik:
- Utwórz rekord
- Zaktualizuj konkretne pole(a)
- Zmień status (złóż, zatwierdź, zarchiwizuj)
- Usuń (najlepiej miękkie usunięcie do potwierdzenia)
Małe akcje są łatwiejsze do debugowania. Jeśli support musi pomóc użytkownikowi, dużo łatwiej przeczytać „Zmiana statusu: Szkic -> Wysłany” niż badać ogromny blob JSON.
Dla każdej akcji w kolejce przechowuj wystarczające metadane, aby bezpiecznie ją odtworzyć i wykryć konflikty:
- Identyfikator rekordu (oraz tymczasowy lokalny ID dla nowo utworzonych rekordów)
- Znacznik czasu akcji i identyfikator urządzenia
- Oczekiwana wersja (lub ostatni znany czas aktualizacji) rekordu
- Payload (konkretne zmienione pola, najlepiej wraz ze starą wartością gdy to możliwe)
- Klucz idempotencyjny (unikalne ID akcji, by ponowienia nie tworzyły duplikatów)
Ta oczekiwana wersja to klucz do uczciwego obsługiwania konfliktów. Jeśli wersja serwera się posunęła, możesz wstrzymać i poprosić o decyzję zamiast cicho nadpisywać kogoś innego.
Niektóre akcje muszą być zastosowane razem, bo użytkownik widzi je jako jeden krok. Na przykład „Utwórz zamówienie” plus „Dodaj trzy pozycje” powinny się powieść albo nie powieść w całości. Przechowaj ID grupy (lub ID transakcji), żeby silnik synchronizacji mógł wysłać je razem i albo zatwierdzić wszystkie, albo pozostawić je wszystkie oczekujące.
Czy budujesz ręcznie, czy w AppMaster, cel jest ten sam: każda zmiana jest zapisana raz, odtwarzana bezpiecznie i wytłumaczalna, gdy coś nie pasuje.
Reguły rozwiązywania konfliktów, które możesz wytłumaczyć użytkownikom
Konflikty są normalne. Celem nie jest ich wyeliminowanie. Celem jest sprawić, by były rzadkie, bezpieczne i łatwe do wyjaśnienia, gdy się pojawią.
Nazwij moment konfliktu: aplikacja wysyła zmianę, a serwer odpowiada: „Ten rekord nie jest w wersji, którą zaczęłaś edytować.” Dlatego wersjonowanie ma znaczenie.
Przy każdym rekordzie trzymaj dwie wartości:
- Wersja serwera (aktualna wersja na serwerze)
- Oczekiwana wersja (wersja, którą myślał, że edytuje telefon)
Jeśli oczekiwana wersja się zgadza, zaakceptuj aktualizację i podbij numer wersji. Jeśli nie, zastosuj swoją regułę konfliktu.
Wybierz regułę per typ danych (nie jedną regułę dla wszystkiego)
Różne dane wymagają różnych reguł. Pole statusu to nie to samo co długi tekst notatki.
Reguły, które użytkownicy zazwyczaj rozumieją:
- Last write wins: OK dla niskiego ryzyka pól, np. preferencji widoku.
- Scalanie pól: najlepsze, gdy pola są niezależne (status vs notatki).
- Zapytaj użytkownika: najlepsze dla ryzykownych edycji, jak cena, uprawnienia czy sumy.
- Serwer wygrywa z kopią: zachowaj wartość serwera, ale zapisz edycję użytkownika jako szkic, który można ponownie zastosować.
W AppMaster te reguły dobrze mapują się na logikę wizualną: sprawdź wersje, porównaj pola, potem wybierz ścieżkę.
Zdecyduj, jak zachowują się usunięcia (albo stracisz dane)
Usunięcia są trudnym przypadkiem. Użyj tombstone (znacznik „usunięte”) zamiast natychmiastowego wykreślenia rekordu. Potem zdecyduj, co się stanie, jeśli ktoś edytował rekord, który gdzie indziej został usunięty.
Jasna reguła to: „Usunięcia wygrywają, ale można przywrócić.” Przykład: handlowiec edytuje notatkę klienta będąc offline, a admin usuwa tego klienta. Przy synchronizacji aplikacja powinna pokazać: „Klient został usunięty. Przywrócić, by zastosować swoją notatkę?” To unika cichej utraty i daje kontrolę użytkownikowi.
Ponawiania i stany błędów: trzymaj to przewidywalnym
Gdy synchronizacja zawodzi, większości użytkowników nie obchodzi przyczyna. Chcą wiedzieć, czy ich praca jest bezpieczna i co się stanie dalej. Przewidywalny zestaw stanów zapobiega panice i zgłoszeniom do supportu.
Zacznij od małego, widocznego modelu statusów i trzymaj go spójnym na ekranach:
- Queued: zapisane na urządzeniu, czekają na sieć
- Syncing: wysyłane teraz
- Sent: potwierdzone przez serwer
- Failed: nie udało się wysłać, będzie ponawiane lub wymaga uwagi
- Needs review: wysłane, ale serwer odrzucił lub oznaczył do weryfikacji
Ponawiania powinny oszczędzać baterię i transfer. Użyj szybkich ponowień na początku (na wypadek krótkiego zrywu sygnału), potem zwalniaj. Proste odwzorowanie 1 min, 5 min, 15 min, potem co godzinę jest łatwe do rozumienia. Ponawiaj tylko kiedy ma to sens (nie ponawiaj wiecznie zmiany, która jest błędna).
Różnicuj działania zależnie od błędu, bo następny krok będzie inny:
- Offline / brak sieci: pozostań w kolejce, ponów przy dostępności
- Timeout / serwer niedostępny: oznacz jako nieudane, auto-ponawiaj z backoffem
- Wygasła autoryzacja: wstrzymaj synchronizację i poproś użytkownika o ponowne zalogowanie
- Błąd walidacji (złe dane): wymaga przeglądu, pokaż co poprawić
- Konflikt (rekord się zmienił): wymaga przeglądu, skieruj do reguł konfliktu
Idempotencja to to, co czyni ponowienia bezpiecznymi. Każda zmiana powinna mieć unikalne ID akcji (zwykle UUID) wysyłane z żądaniem. Jeśli aplikacja wyśle tę samą zmianę ponownie, serwer powinien rozpoznać ID i zwrócić ten sam rezultat zamiast tworzyć duplikaty.
Przykład: technik zapisuje ukończone zadanie będąc offline, potem wchodzi do windy. Aplikacja wysyła aktualizację, kończy się timeout, i ponawia później. Z kluczem akcji drugie wysłanie jest nieszkodliwe. Bez niego możesz stworzyć zdublowane „ukończone” zdarzenia.
W AppMaster traktuj te stany i reguły jako elementy pierwszej klasy i włącz je w proces synchronizacji, żeby Twoje aplikacje Kotlin i SwiftUI zachowywały się wszędzie tak samo.
UX oczekujących zmian: co widzi użytkownik i co może zrobić
Ludzie powinni czuć się bezpiecznie używając aplikacji offline. Dobry UX dla „pending changes” jest spokojny i przewidywalny: potwierdza, że praca jest zapisana na urządzeniu i pokazuje jasny następny krok.
Subtelny wskaźnik działa lepiej niż baner ostrzegawczy. Na przykład pokaż małą ikonę „Synchronizuję” w nagłówku, albo cichą etykietę „3 oczekujące” na ekranie, gdzie wykonywane są edycje. Kolorów ostrzegawczych używaj tylko dla realnego zagrożenia (np. „nie można wysłać, bo jesteś wylogowany”).
Daj użytkownikom jedno miejsce, by zrozumieć, co się dzieje. Prosta skrzynka wysyłkowa (Outbox) lub ekran Oczekujące zmiany może listować pozycje prostym językiem, np. „Dodano komentarz do Zgłoszenia 104” albo „Zdjęcie profilowe zaktualizowane.” Taka przejrzystość zapobiega panice i zmniejsza zgłoszenia do supportu.
Co użytkownicy mogą zrobić
Większość osób potrzebuje kilku prostych akcji, spójnych w całej aplikacji:
- Spróbuj ponownie teraz
- Edytuj ponownie (tworzy nowszą zmianę)
- Odrzuć lokalną zmianę
- Skopiuj szczegóły (przydatne przy zgłaszaniu problemu)
Utrzymuj etykiety statusów proste: Pending, Syncing, Failed. Gdy coś nie powiedzie się, wyjaśnij to jak człowiek: „Nie można przesłać. Brak internetu.” lub „Odrzucono, bo ten rekord został zmieniony przez kogoś innego.” Unikaj kodów błędów.
Nie blokuj całej aplikacji
Blokuj tylko te akcje, które naprawdę wymagają bycia online, jak „Płać przez Stripe” czy „Zaproś nowego użytkownika.” Wszystko inne powinno nadal działać, w tym przeglądanie ostatnich danych i tworzenie nowych szkiców.
Realistyczny przepływ: technik w terenie edytuje raport pracy w piwnicy. Aplikacja pokazuje „1 oczekujące” i pozwala mu dalej pracować. Później zmienia się na „Synchronizuję”, potem usuwa automatycznie. Jeśli się nie powiedzie, raport pozostaje dostępny, oznaczony jako „Nieudane”, z jednym przyciskiem „Spróbuj teraz”.
Jeśli budujesz w AppMaster, zamodeluj te stany jako część każdego rekordu (pending, failed, synced), żeby UI mogło je wszędzie odzwierciedlać bez wyjątkowych ekranów.
Autoryzacja, uprawnienia i bezpieczeństwo w trybie offline
Tryb offline zmienia model bezpieczeństwa. Użytkownik może wykonać akcje, gdy nie ma połączenia, ale serwer pozostaje źródłem prawdy. Traktuj każdą kolejkę zmian jako „żądanie”, a nie „zatwierdzenie”.
Wygasanie logowania podczas bycia offline
Tokeny wygasają. Kiedy to nastąpi offline, pozwól użytkownikowi kontynuować tworzenie edycji i zapisz je jako oczekujące. Nie udawaj, że akcje wymagające potwierdzenia serwera są zakończone. Oznacz je jako oczekujące, aż do następnego pomyślnego odświeżenia autoryzacji.
Gdy aplikacja znów będzie online, spróbuj wykonać ciche odświeżenie. Jeśli musisz poprosić użytkownika o ponowne zalogowanie, zrób to raz, a potem wznów synchronizację automatycznie.
Po ponownym zalogowaniu zweryfikuj każde oczekujące zadanie przed wysłaniem. Tożsamość użytkownika mogła się zmienić (współdzielone urządzenie), i stare edycje nie powinny synchronizować się pod złym kontem.
Zmiany uprawnień i zabronione akcje
Uprawnienia mogą się zmienić, gdy użytkownik jest offline. Edycja, która wczoraj była dozwolona, dziś może być zabroniona. Obsłuż to jawnie:
- Sprawdzaj uprawnienia po stronie serwera dla każdej akcji w kolejce
- Jeśli zabronione, zatrzymaj tę pozycję i pokaż jasny powód
- Zachowaj lokalną edycję, by użytkownik mógł ją skopiować lub poprosić o dostęp
- Unikaj powtarzanych ponowień dla błędów „forbidden”
Przykład: agent supportu edytuje notatkę klienta na locie. Przez noc jego rola zostaje usunięta. Przy synchronizacji serwer odrzuca aktualizację. Aplikacja powinna pokazać „Nie można przesłać: nie masz już dostępu” i zachować notatkę jako lokalny szkic.
Wrażliwe dane przechowywane offline
Przechowuj minimalne dane potrzebne do renderowania ekranów i odtworzenia kolejki. Szyfruj magazyn offline, unikaj cache’owania sekretów i miej jasne reguły przy wylogowaniu (np. wyczyść lokalne dane albo zachowaj szkice tylko po wyraźnej zgodzie użytkownika). Jeśli budujesz z AppMaster, zacznij od jego modułu autoryzacji i zaprojektuj kolejkę tak, by zawsze czekała na ważną sesję przed wysłaniem zmian.
Typowe pułapki prowadzące do utraty pracy lub duplikatów
Większość błędów offline nie jest wyszukana. Wynikają z kilku małych decyzji, które wydają się nieszkodliwe przy testach na idealnym Wi‑Fi, a potem psują realną pracę.
Jedną z częstych awarii są ciche nadpisania. Jeśli aplikacja prześle starszą wersję, a serwer ją zaakceptuje bez sprawdzania, możesz skasować czyjąś nowszą edycję i nikt nie zauważy dopóki nie będzie za późno. Synchronizuj z numerem wersji (lub znacznikiem updatedAt) i odmawiaj nadpisania, gdy serwer poszedł do przodu — tak użytkownik dostaje wyraźny wybór.
Inna pułapka to burza ponowień. Gdy telefon odzyska słabe połączenie, aplikacja może bombardować backend co kilka sekund, wyczerpując baterię i tworząc duplikaty. Ponawiania powinny być spokojne: zwalniaj po każdym niepowodzeniu i dodaj niewielką losowość, żeby tysiące urządzeń nie ponawiały jednocześnie.
Błędy, które najczęściej prowadzą do utraty pracy lub duplikatów:
- Traktowanie każdego błędu jako „sieciowego”: rozdziel błędy trwałe (złe dane, brak uprawnień) od tymczasowych (timeout).
- Ukrywanie błędów synchronizacji: jeśli użytkownicy nie widzą, co się nie udało, robią zadanie ponownie i tworzą dwa rekordy.
- Wysyłanie tej samej zmiany dwa razy bez ochrony: zawsze dołączaj unikalny request ID, by serwer rozpoznawał duplikaty.
- Automatyczne scalanie pól tekstowych bez powiadomienia: jeśli łączysz edycje automatycznie, pozwól użytkownikom przejrzeć wynik, gdy ma to znaczenie.
- Tworzenie rekordów offline bez stabilnego ID: używaj tymczasowego lokalnego ID i mapuj go na ID serwera po uploadzie, żeby późniejsze edycje nie stworzyły drugiego rekordu.
Szybki przykład: technik tworzy nową „Wizytę na miejscu” offline, potem edytuje ją dwukrotnie przed połączeniem. Jeśli wywołanie tworzące zostanie powtórzone i utworzy dwa rekordy na serwerze, późniejsze edycje mogą przypisać się do złego rekordu. Stabilne ID i deduplikacja po stronie serwera temu zapobiegają.
Jeśli budujesz to w AppMaster, zasady się nie zmieniają. Różnica jest w tym, gdzie je implementujesz: w logice synchronizacji, modelu danych i ekranach pokazujących „failed” vs „sent”.
Przykład scenariusza: dwie osoby edytują ten sam rekord
Technik terenowy, Maya, aktualizuje zgłoszenie „Praca #1842” w piwnicy bez sygnału. Zmienia status z „W toku” na „Zakończone” i dodaje notatkę: „Wymieniono zawór, test OK.” Aplikacja zapisuje natychmiast i pokazuje to jako oczekujące.
Na górze, jej współpracownik Leo jest online i w tym samym czasie edytuje to samo zgłoszenie. Zmienia termin i przypisuje zadanie innemu technikowi, bo klient dzwonił z aktualizacją.
Gdy Maya zyskuje sygnał, synchronizacja w tle zaczyna działać cicho. Oto, co dzieje się w przewidywalnym, przyjaznym dla użytkownika przepływie:
- Zmiana Mayi jest w kolejce synchronizacji (ID zadania, zmienione pola, timestamp i wersja rekordu, którą widziała).
- Aplikacja próbuje wysłać. Serwer odpowiada: „To zadanie było zaktualizowane od czasu twojej wersji” (konflikt).
- Uruchamia się reguła konfliktu: status i notatki można scalić, ale zmiany przypisania wygrywają, jeśli były późniejsze na serwerze.
- Serwer akceptuje scalony wynik: status = „Zakończone” (od Mayi), notatka dodana (od Mayi), przypisanie technika = wybór Leo.
- Zgłoszenie otwiera się ponownie w aplikacji Mayi z jasnym banerem: „Zsynchronizowano z aktualizacjami. Przypisanie zmieniło się podczas twojej nieobecności.” Mały przycisk „Przejrzyj” pokazuje, co się zmieniło.
Dodaj teraz moment awarii: token logowania Mayi wygasł, gdy była offline. Pierwsza próba synchronizacji kończy się „Wymagane logowanie”. Aplikacja zachowuje jej edycje, oznacza je jako „Wstrzymane” i pokazuje prosty monit. Po zalogowaniu synchronizacja wznawia się automatycznie bez konieczności przepisywania czegokolwiek.
Jeśli pojawi się problem walidacyjny (np. „Zakończenie” wymaga zdjęcia), aplikacja nie powinna zgadywać. Oznacza pozycję jako „Wymaga uwagi”, dokładnie mówi, co dodać, i pozwala ponownie wysłać.
Platformy takie jak AppMaster mogą tu pomóc, bo pozwalają zaprojektować kolejkę, reguły konfliktów i UX stanów oczekujących wizualnie, a jednocześnie dostarczyć prawdziwe natywne aplikacje Kotlin i SwiftUI.
Szybka lista kontrolna i następne kroki
Traktuj synchronizację offline jako funkcję end-to-end, którą możesz testować, a nie jako zbiór napraw. Cel jest prosty: użytkownicy nigdy nie powinni się zastanawiać, czy ich praca jest zapisana, a aplikacja nie powinna tworzyć niespodziewanych duplikatów.
Krótka lista kontrolna, by potwierdzić solidne podstawy:
- Kolejka synchronizacji jest przechowywana na urządzeniu, każda zmiana ma stabilne lokalne ID plus ID serwera gdy dostępne.
- Istnieją jasne statusy (queued, syncing, sent, failed, needs review) i są używane konsekwentnie.
- Żądania są idempotentne (bezpieczne do ponowienia), każde działanie ma klucz idempotencyjny.
- Rekordy mają wersjonowanie (updatedAt, numer rewizji lub ETag), by wykrywać konflikty.
- Reguły konfliktów są zapisane prostym językiem (co wygrywa, co się scala, kiedy pytasz użytkownika).
Gdy to masz, zweryfikuj, czy doświadczenie jest tak samo solidne jak model danych. Użytkownicy powinni widzieć, co jest oczekujące, rozumieć, co nie zadziałało i podjąć działania bez strachu przed utratą pracy.
Testuj scenariusze dopasowane do realnego życia:
- Edycje w trybie samolotowym: utwórz, zaktualizuj, usuń, potem połącz.
- Niestabilna sieć: przerwij połączenie w trakcie sync i upewnij się, że ponowienia nie tworzą duplikatów.
- Aplikacja zamknięta: wymuś zamknięcie podczas wysyłania, otwórz ponownie, potwierdź, że kolejka się odtwarza.
- Przesunięcie zegara: urządzenie ma złą godzinę, upewnij się, że wykrywanie konfliktów nadal działa.
- Duplikowane stuknięcia: użytkownik naciska Zapisz dwa razy, upewnij się, że to staje się jedną zmianą na serwerze.
Zaprojektuj prototyp całego przepływu przed dopracowaniem UI. Zbuduj jeden ekran, jeden typ rekordu i jeden przypadek konfliktu (dwie edycje tego samego pola). Dodaj prosty obszar statusu synchronizacji, przycisk Retry dla błędów i jeden ekran konfliktu. Gdy to zadziała, powielaj dla kolejnych ekranów.
Jeśli budujesz bez kodu, AppMaster (appmaster.io) może wygenerować natywne aplikacje Kotlin i SwiftUI razem z backendem, więc możesz skupić się na kolejce, sprawdzaniu wersji i stanach widocznych dla użytkownika zamiast na ręcznym łączeniu wszystkiego.


