A jaki w tym problem że user uruchomi aplikację jak trwa backup? Kolega napisał że jeśli takie coś zajdzie to na starcie user dostanie progress bar'a z informacją o zaawansowaniu backupu...
Nie jest to problem jako taki. Problem jest jednak w tym, że do takiego wątku, który będzie wykonywał tę czynność musi istnieć gdzieś wskazanie, informacja o tym. Dlatego na starcie pisałem o możliwości pokrycia application, aby tam umieścić zmienną. Chociaż jak teraz na to patrzę było to bez sensu, wystarczy jakiś singleton. W normalnym operowaniu przy activity na wątkach nie ma problemu. Np. masz wątek, coś robi wyświetla progress, obracasz urządzenie, zmienia się orientacja activity jest niszczone, dialog jest niszczony. Ale tutaj sprawę załatwia mechanizm
non-configuration instance data który pozwala odtworzyć odwołania, a co za tym idzie odtworzyć dialog i operacja leci dalej wizualizując dalsze postępy. Szczerze mówiąc sporo czasu straciłem na zrobieniu tego fragmentu kodu w taki sposób, aby wszystko działało w każdej sytuacji.
Po co chcecie wykorzystywać jakiegoś schedulera (mniejsza o to jaki on ma być)?
Jeżeli w androidzie coś ma zostać wykonane w tle, to trzeba użyć usługi i wszystko na ten temat. To czy będzie działała w tym samym procesie co aplikacja, czy innym jest już szczegółem. (...)
Może, ale już abstrahując, bo usługa tutaj to ten sam process, zawsze pisząc cokolwiek starałem się minimalizować zasobożerność. Jasne, można odpalić 15 procesów, każdy robiący co innego, ale jak dla mnie to nie tędy droga. Tym bardziej wydaje mi się to aktualne w przypadku urządzeń mobilnych, które z samej definicji mają ograniczone zasoby.
(...) Przy starcie aplikacji stawiasz sobie serwis, przy jej "końcu" uruchamiasz w tym serwisie backup i wszystko. Warto zrobić dodatkowo przesunięcie serwisu na pierwszy plan, bo jeżeli usługa nie ma żadnej pierwszoplanowej activity podpiętej do siebie, to może zostać zabita w dowolnym momencie.
Używanie AlarmManager jest o tyle bez sensu, że nikt ci nie zagwarantuje, że użytkownik nie uruchomi w tym momencie twojej aplikacji - powiesz mu, że źle kliknął? (...)
Wiem, może to przekombinowane, ale spójrz na to z punktu widzenia wykorzystania aplikacji, a nie tylko jako problemu do rozwiązania z punktu widzenia programisty
🙂 .
Postaram się to dokładniej opisać. Głównym problemem jest wykrycie zamknięcia aplikacji i te kombinacje z opóźnieniem, AlarmManagerem są z także z tym związane. Wynika to z prostego scenariuszu: ktoś pracuje w aplikacji, backup ma się wykonać jak faktycznie skończy pracować. Fakt, w 100% nie da się tego wykryć, bo nie znasz jego myśli, ale ja przynajmniej staram się to zrobić. To co jest chyba jasne, aplikacja w Androidzie może "zakończyć" się dwojako: niszczone jest główne activity więc jego onDestroy jest niejako 100% momentem w którym można odpalić backup oraz drugi przypadek aktualne activity (niekoniecznie główne) jest "minimalizowane" w raz cała aplikacją (przycisk Home, przejście do innej aplikacji). I problem stanowi ten drugi przypadek. Tutaj zaraz po ukryciu activity i zarazem aplikacji nie można odpalać backupu, tego chce uniknąć, tutaj jest to niedomyślenia. Wyobraź sobie coś takiego (ja mam tak często):
wpisuję transakcje które aktualnie realizuję (np. opłacam rachunki),
zrobiłem jeden przelew, wpisałem go do programu - w tym momencie aplikacja wykrywa dokonanie zmian, dodatkowo od ostatniego backupu minął ponad tydzień, więc aplikacja już wie, że trzeba będzie zrobić backup,
robię drugi przelew, bank prosi o potwierdzenie przelewu SMSem,
dostaję SMSa, przełączam się na aplikację od SMSów, mój program ląduje w tle - jest problem.
W powyższym scenariuszu gdybym szedł tak jak piszesz, czysto "programistycznie", wykrywam "zamknięcie" aplikacji, robię backup? Błąd. Jasne, ktoś wróci do aplikacji, ja wyświetlę komunikat, że trwa backup, nic się nie wysypie, ale dla mnie jest to nie do przyjęcia. I to z dwóch powodów. Po pierwsze, dlaczego userowi przerywa się wpisywanie, pracę w aplikacji czymś co ma się robić automatycznie, w tle, dla dobra usera, a nie dla jego irytowania. A po drugie, zrobienie w tym momencie backupu spowoduje, że dzisiejsze transakcje nie zostaną zarchiwizowane - jasne, jutrzejsze także nie będą do przyszłego tygodnia. Ani nawet te które zrobię pewnie z 3 godziny, ale dlaczego mają zostać zarchiwizowane tylko 2 pierwsze z 5 które zrobiłem?
Rozpisałem się, ale chyba to wystarczy, aby rozjaśnić mój problem. Timer lub AlarmManager rozwiązuje tu problem o tyle, że można w tym drugim przypadku opóźnić odpalenie backupu o np. 15 minut, a wtedy można mieć pewność (oczywiście nie 100%), że pewnie user już skończył pracę z programem.
Używanie przycisku home do "kończenia" aplikacji nie jest raczej także niczym dziwnym. Jasne, gdybym robił aplikację tylko dla siebie (a poniekąd robię ją głównie dla siebie z uwagi na brak alternatyw po przesiadce na Androida), to nie byłby to problem. Ale zamierzam ją także upublicznić 🙂 .
(...) Największym problemem jaki tu widzę, jest twoje ograniczenie, że backup nie może być wykonywany podczas działania aplikacji - wiesz to na pewno, czy tylko ci się wydaje? Zdjęcie tego ograniczenia sprowadza złożoność problemu do zera, więc warto je przemyśleć.
To taki średni problem. Teoretycznie można by pewnie puścić odczyt z bazy i robić backup w oddzielnym wątku, gdy nawet aplikacja pracuje. Ale jak napisałem wyżej, problemem nie jest suche odpalanie backupu co 7 dni. Bo po co robić backup tych samych danych, jeśli nie wprowadzono zmian (to w kontekście po co robić np. usługę, można by przecież tak: user odpala program, od ostatniego odpalenia minęło 7 dni, robimy po prostu backup).
---------- Post dołączono o 10:03 ---------- Poprzedni post napisano o 09:55 ----------
Dla mnie cały ten problem jest mocno sztuczny i wydumany. Załóżmy, że aplikacja to jakiś tam specjalizowany notatnik - czyli użytkownik coś wprowadza, zapisujemy to w SQLIte - w czym problem? Przecież z bazy SQLite można jednocześnie czytać(robić backup) i zapisywać do niej z poziomu UI (...) brał bym "transaction log" z bazy (...)Jeżeli coś takiego jest zbyt skomplikowane, to można podejść jeszcze inaczej - przy starcie aplikacji (bo to jedyny stały i pewny moment w całym lifecycle), przed otwarciem bazy danych, wykonać kopię pliku bazy (<1s), uruchomić service, który ten plik będzie sobie wysyłał, czy nawet przetwarzał jeśli jest taka potrzeba.
Zmieniłeś troszkę swój post, ale odniosę się do powyższego. Obecnie struktura bazy w mojej aplikacji składa się z 8 tabel, wszystkie są zależne od siebie (może lista ci coś rozjaśni: Accounts, Categories, Exchanges, Projects, Schedules, Splits, Transactions, Transfers). Robienie tego jak wyżej dopiero byłoby totalnym przekombinowaniem, bez urazy
🙂 . Co do backupu na starcie, to na moich danych (a mam ich z 7 lat bo wcześniej korzystałem z innych programów do tego celu na innych platformach) trwa około 8 sekund plus powód który wspomniałem w poprzednim poście, suchy backup na starcie jest bez sensu.
PS. Replikacje to już troszkę przeżytek 😉