Logika programu z wątkami

0

Witam,

Robię program do sterowania bramą wjazdową (tak w dużym uproszczeniu: można ją zamknąć i otworzyć i cały czas jest podgląd jej stanu). Transmisja z serwerem przez TCP.
Mam już aplikację na Androida w Delphi (:P) ale chcę ją napisać ponownie w Kotlinie. I mam problem z doborem logiki.
Obecnie jest tak, że program wyświetla główne okno z przyciskami (otwórz/zamknij) i etykietą (status) a w tle chodzi sobie wątek który co kilka sekund odświeża mi stan bramy. Wciśnięcie przycisku powoduje ustawienie znacznika w wątku żeby wysłał dane polecenie. I tyle.
Całość transmisji jest wyrzucona do wątku bo w zależności od jakości połączenia to działa lepiej bądź gorzej a tak nie wieszam programu.

I teraz pytanie - jak to zrobić w Kotlinie żeby było tak jak być powinno? Mam świadomość że tu program pisze się bardziej zadaniowo dlatego może bez sensu będzie powtarzanie takiej logiki jak tam. A chcę osiągnąć to samo. Transmisja jako taka nie ma znaczenia bo serwer jest mój (Delphi :P), istotne tylko żeby jakość połączenia nie wpływała na używalność programu. Ma sens zachowanie starej logiki czy lepiej przejść na rozwiązanie typu "każde polecenie tworzy osobny wątek który ma jedno zadanie, a potem znika"?
I przy okazji - czy aż Thread jest mi potrzebny? Coroutine nie będzie lepszym rozwiązaniem?

3

W ogóle nie tak
Powiem w ogólności, że bardzo niewiele śrdoowisk / frameworków odnosi się z entuzjazmem do ręcznych Threadów
A w szczególności dla androida proponowane jest AsyncTask<A,B,C> np

public abstract class
MojaNajlepszaOperacjaSieciowa extends AsyncTask<String, String, StringBuffer> {

https://developer.android.com/reference/android/os/AsyncTask

0

Dlaczego nie coroutines dla otworz/zamknij oraz np jakis service dla trzymania/pobierania stanu bramy w tle?

A ten serwis w tle nie może zająć się całą transmisją? Wydaje mi się logiczne (?) że takie coś może, a nawet powinien, robić jeden osobny wątek który reszcie programu będzie udostępniał tylko status bramy i metodę pozwalającą zadać polecenie. Takie coś mam już teraz, tylko wydaje mi się że to nie do końca pasuje do Androidowej logiki (?).

2

Nie musisz tworzyc osobnego watku, po ta sa wlasnie coroutines zeby obciazajace, blokujace taski nie obciazaly domyslnego UI thread.
Coroutines nie sa na sztywno przypisane do konkretnego watku, wynosisz sobie dany blok kodu poza obecny watek, wykonanie kodu nie obciaza tego watku i ewentualnie gdy kod sie wykona ten watek(albo inny) dostaje rezultat.
Masz zadanie do wykonania, uruchamiasz kod w odpowiednim coroutine scope dzieki czemu uwalniasz watek od obciazenia danym zadaniem.
Coroutines w ogole sa lekkie i przy takich taskach nie obciazajace, dzialaja inaczej niz watki w zalozeniach.

Jeszcze sobie doczytujac, docsy rowniez wydaje mi sie rekomndowaly by uzycie Coroutines z Kotlinem dla Twojego use casu. Jesli musisz miec caly czas(o ile system nie ubije) chodzacy task w tle to sprawdz rowniez WorkManager
https://developer.android.com/guide/background

Mam nadzieje ze ktos bardziej doswiadczony pomoze konkretniej, bardzo jestem ciekaw jak to rozwiazac dobrze :)

3

a w tle chodzi sobie wątek który co kilka sekund odświeża mi stan bramy

ogólnie to jestem ogromnym przeciwnikiem odpytywania serwera o dane co jakiś czas. To serwer powinien powiadomić aplikację mobilną o tym, że coś się zmieniło. Po pierwsze, nie marnujesz baterii w urządzeniu mobilnym, po drugie nie marnujesz zasobów na odpytanie serwera tylko po to żeby sprawdzić czy coś się może zmieniło. Aleeeeeee zdaję sobie też sprawę, że nie wszędzie da się zrobić idealnie :D

W twoim przypadku czy użyjesz, wątków, async taska, rxjavy, korutyn to zrobisz to tylko dlatego, żeby nie blokować UIThread. Każde z tych rozwiązań oferuje tę opcję. Kwestia tego, co jest aktualnie na topie. AsyncTask staroć i lepiej o nim zapomnieć, rxjava to armata na komara. Własne wątki, fajnie, ale trzeba się nimi interesować, przejmować. Korutyny -ideolo.

Te rozwiązania wyżej dadzą Ci opcję odświeżania danych w momencie kiedy apka nie jest w background. Jak apka zejdzie do background to powinna przestać odpytywać serwer. A jeśli już chcesz to zrobić koniecznie, to polecam Worker'y. Jest coś takiego jak CoroutineWorker i dzięki niemu, możesz odpytywać serwer co jakiś czas w tle. Oczywiście pamiętając, że workery są stworzone pod optymalizacje baterii i że nie możesz polegać na dokładności wykonania zadania.

0

Odpytywanie wynika z faktu że serwer jest jeden a klientów maksymalnie kilku (nie, nie kilka tysięcy; to brama do domu) i wygodniej mi pytać o to co jest potrzebne niż bawić się w rejestrowanie co kto chciał i pilnowanie jego sesji. Nie czułem takiej potrzeby więc o tym nie wspominałem, ale brama to fragment całości - bo są tu jeszcze kamery i inne cuda na kiju. A i klienci na różne systemy czy urządzenia.

Poza tym aplikacja (na Androida) ma działać tylko jak jest aktywna. Jej praca w tle nie ma sensu.

Tu dodam że całość ma charakter bajerancko-edukacyjny bo lubię uczyć się nowości robiąc rzeczy użyteczne, a taki program uruchomiony przez Android Auto to będzie to. Przy okazji nie chcę przekombinować na początku, stąd w ogóle ten temat.

Ale wiem już chyba wszystko co chciałem, także dzięki wielkie.

0

@dziobu:

Kic i jesteś w temacie klienta. Kic kic, i serwera.
masz nadzieję tak się
a) dogadać
b) zdrowo zaplanować swoje oprogramowanie ?

0

Na bieżącym etapie to chcę zrobić tak żeby nie przekombinować a żeby działało. Potem stopniowo dodam to czego chcę aż dojdę do momentu gdy dalsze doróbki będą bez sensu. Wtedy napiszę wersję 2.0 już tak jak się powinno to robić. Zakładam że wtedy nie będę musiał już pytać o takie pierdoły.

0

Ale to nie lepiej zaprojektowac tak zeby serwer mial komplet informacji a aplikacje klienckie beda sie odpytywac o to co im potrzebne? Pytam bo jednak pisales o jakims watku ktory ma dzialac w tle i pobierac info co kilka sekund co mozna rozwiazac sprawniej.
Tak czy inaczej gratulacje za mega projekt :)

0

No ale tak właśnie jest. Serwer ma wszystko a aplikacja końcowa pyta tylko o to czego potrzebuje. W końcu nie każdy odbiorca ściąga komplet informacji i też nie każdy potrzebuje tego od razu.
Tak jest też łatwiej z perspektywy kogoś kto się uczy; w końcu zamiast obsługiwać jakieś asynchroniczne procedury zwrotne czy inne zdarzenia prościej napisać ciurkiem w wątku pętlę typu "wyślij zapytanie - czekaj na odpowiedź". W sytuacji gdy z serwerem łączy się maksymalnie 2-3 użytkowników jednocześnie, to aż szkoda komplikować cokolwiek. Zwłaszcza że teraz mowa o prostej aplikacji która ma pozwolić na sterowanie bramą z poziomu ekranu w samochodzie. To program który uruchamia się rzadko, na nie więcej niż paredziesiąt sekund. Myślę że to proste na początek; wersja z Delphi działa i ma się dobrze, ale nie jestem w stanie ogarnąć tam AA. Zresztą w końcu mam sensowny powód żeby nauczyć się czegoś nowego i nie chcę tego zmarnować.

1

Zależy czego oczekujesz i kto inicjuje komunikację.
Jeżeli potrzebujesz czegoś co działa długo (być może w tle), to w A masz taki komponent jak Service. Piszesz podobnie jak Activity, jest parę możliwych sposobów komunikacji, np. Intenty, które możesz sobie przechwycić w Activity i odpowiednio zareagować.
Jeżeli to brama inicjuje komunikację, przez jakieś wiadomości, to masz bodajże Intent Handler / intent filter. Czyli rejestrujesz sobie api w jakimś tam Firebase, brama jak się otworzy, to wysyła do googla informację "otworzyłam się", ten wysyła ją do twojego telefonu i pozostaje ją obsłużyć.
Wreszcie masz wątki, czyli coroutines Kotlinowe, a w Javie dość wygodne opakowane w AsyncTask, które wykonuje się gdzieś tam na boku i ostatecznie wysyła przez handler wiadomość do wątku w którym ten handler stworzono.

Cała komunikacja powinna być robiona poza głównym wątkiem, czyli jeżeli masz np. guzik, który ma pobrać jakieś dane przez internet i je wyświetlić jakoś tam, to nie możesz zrobić tego na wątku UI (głównym), tylko odpalasz nowy, roisz komunikację, jak komunikacja wyjdzie, to na wątku głównym wyświetlasz jej efekty.

Android ma zabezpieczenie przed długotrwającymi operacjami na wątku użytkownika (UI), jeżeli przez kilka sekund UI nie reaguje, to system ubija Activity.

1 użytkowników online, w tym zalogowanych: 0, gości: 1