Flutter - zrozumienie fenomenu Riverpod

3

Witam.
W związku z tym, że sporo osób (nie tylko tutaj) odradza korzystanie z GetX, ponieważ jest "do wszystkiego". Postanowiłem pochylić się nad Riverpod. Problem polega na tym, że ja nie potrafię przełożyć dokumentacji, tutoriali na mój projekt. Nie potrafię zrozumieć providerów.

PRZYKŁAD

  1. Lista dokumentów - wstępnie powinno być FutureProvider, ponieważ dokumenty są pobierane z API, ale...
    a. co z filtrowaniem?
    b. co z szukajką?
    c. czy to wtedy już jest StateNotifierProvider?
    d. szukajka jest uruchamiana z AppBar - czy tzn, że Consumer powinien być na cały Scaffold? Coś czuje, że to kiepsko wydajne...

  2. Nowy/Edycja dokumentu - jak ogarnąć tworzenie, edycję obiektu. Muszę pobrać na formatkę formy płatności, kontrahentów, towary.
    a. dodatkowa logika, w której wybór kontrahenta decyduje o terminie płatności (w przypadku przelewu)
    b. przeliczanie netto, vat, brutto po dodaniu lub zmodyfikowaniu pozycji dokumentu
    c. serwis, który ogarnia zaznaczanie pozycji na dokumencie, aby wykonać jakąś operację "hurtowo" (usuwanie, zmiana ilości)

  3. Koszyk zakupów - to akurat nie musi być serwerowe. Koszyk może być lokalnie więc tutaj zapytań do API nie będzie ale
    a. ilość towarów w koszyku powinna się pokazać/odświeżać na głównej stronie.
    b. tutaj również dobry byłby serwis, który ogarnia zaznaczanie i hurtowe operacje
    c. z koszyka przechodzimy na zamówienie (nowy dokument)

Do tego wszystkiego dochodzą takie rzeczy jak konfiguracja aplikacji - dostęp do SharedPreferences z każdego widgeta, w tym też z każdego providera, ponieważ tam będzie zapisany token do API. Może też jakiś provider do zmiany motywu aplikacji (jasny/ciemny).

W GetX mam kontrolery, które mogą mieć obiekty z .obs() i działają jak Angularowe Observable. Wystarczy, że stworzę Obx(() => MojWidget(controller.documents.value)) i wszystko mi się ładnie zmienia i aktualizuje w momencie zmiany filtra czy wyszukania czegoś.

class DocumentsController extends GetxController {
  var isLoading = false.obs;
  var parameters = {
    "filters": "",
    "search": "",
    "orderBy": "",
    "page": "0",
    "limit": "10",
  }.obs;

  var documents = DocumentsResponse().obs;

  final HttpService httpService = Get.find();

  void get(int type) async {
    isLoading(true);
    final response = await httpService.get("documents/type/$type", parameters);
    if (response.statusCode == 200) {
      var json = jsonDecode(response.body);
      documents(DocumentsResponse.fromJson(json));
    }
    isLoading(false);
  }

  void search(int type, String searchText) async {
    isLoading(true);
    final response = await httpService.get("documents/type/$type", parameters);
    if (response.statusCode == 200) {
      var json = jsonDecode(response.body);
      documents(DocumentsResponse.fromJson(json));
    }
    isLoading(false);
  }

Zatrzymałem się na GetBuilder(), GetX(), Obx() i GetView<ControllerClass> - czy tylko mnie się wydaje, że tego jest za dużo, a robi to samo?

PS.
Do Riverpod robię już piąte podejście. Tak jak trochę mi zajęło na zrozumienie GetX'a, tak pewnie potrzebuje trochę czasu na ogarnięcie Riverpod. A projekt jest dość duży i nie chciałbym się uwalić z czymś czego później nie rozbuduje. Na reddicie, jako alternatywa, dla całego GetX'a były - get_it, auto_route, riverpod/provider. Niektórzy też twierdzą, że BLoC jest dobry, ale dla mnie to przeinżynierowany boilerplate.

Czy ktoś byłby w stanie na przykładzie mojego kontrolera pokazać jakby to wyglądało z Riverpod?

0

Nie będę bronił riverpoda bo nie przypadł mi szczególnie do gustu, natomiast get_x którego tak wychwalasz jest naszpikowany odwołaniami do globalnych zmiennych, a sama dokumentacja projektu jest czasami śmieszna a czasami żenująca.

0

Zgadza się, dokumentacja jest dziwna. Prawdopodobnie nie używam go tak jak podmiot liryczny nakazał, ale wyrobiłem sobie pewien schemat, który, jak na razie, działa. Ogarnąłem routing + middleware (route guards), depenedency injection do SharedPreferences oraz HttpService (na razie tylko GET), które są dostępne w całej aplikacji. Mam kontrolery do pobierania danych z API (towary, kontrahenci, dokumenty) z filtrowaniem i szukajką. Mam kontroler do zaznaczania elementów na liście, aby wykonać hurtowe operacje (np. usuwanie, zmiana ilości, ceny), oraz kontroler do zmiany motywu (na razie tryb jasny/ciemy).

Jakie wady niesie za sobą naszpikowany odwołaniami do globalnych zmiennych?

0

Jeśli chodzi o globalne zmienne to może to pomoże: link

A to o czym piszesz najlepiej sobie ogarnąć samemu, wspomagając się pomniejszymi bibliotekami gdzie potrzeba.

0

Po to jest ten post.

  1. Jak ogarnąć samemu?
  2. Jakimi pomniejszymi?
  3. Pomniejsze biblioteki, które oferują DI nie mają zmiennych globalnych?
  4. W "globalnych" SharedPreferences trzymam konfiguracje aplikacji (motyw, ustawienia zachowania) i token do API (token ma w sobie konfiguracje usera i jego uprawnienia). Nie dojdzie do zmiany, aż się nie wyloguje.
  5. Stany poszczególnych obiektów (listy, filtry, szukajki, edycja) są obsługiwane/zmieniane tylko w obrębie widgeta (page), który to powinien robić. Nawet lista towarów jest rozbita na dwa - lista ogólna, lista do dodania pozycji do dokumentu. Myślę jeszcze czy nie zrobić osobnego routingu (page'a) na szukajkę, bo mnie EasySearchBar troszkę drażni swoją funkcjonalnością.

Mam wrażenie, że wyjaśnienia w linku, który podałeś, kompletnie się mnie nie tyczą. Co gorszę, dzieje się znowu to samo co w innym wątku - wymienia się sporo wad GetX'a, ale nikt nie jest w stanie czegoś innego przełożyć na coś więcej niż CRUD, ToDo, czy sprawdzanie pogody... Ja nie piszę ani CRUDa, ani ToDo. Piszę dużą aplikację, która ma się rozwijać jak najdłużej. Za pomocą czego mam to zrobić?

1

Jeśli piszesz poważną aplikację to tym bardziej branie jakiegoś GetXa jest bez sensu. W długoterminowych trzyma się ilość zależności do niezbędnego minimum.

Tłumaczenie tego postami na forum jest trochę bez sensu. Jeśli wrzucisz na githuba jakiś prosty, działający przykład pokazujący twoje problemy, to mógłbym go przerobić na sensowne podejście i wrzucić jako fork. Twój wybór czy Ci się chce.

0

Ok, mogę wrzucić aktualny projekt, który piszę. Tam nie ma dużo, bo to dopiero początek i badam możliwości. Problemem może być API, które nie jest publiczne...

0
  1. Szukajaka w app barze powinna być osobnym bytem(widgetem) i jedynie dostarczać wstępne nastawy dla screena z listą dokumentów który się otworzy po kliknięciu "Szukaj"(o ile dobrze zrozumiałem koncept). Wtedy ten twój osobny byt możesz sobie reużywać w każdym miejscu. Lista dokumentów to osobny widget(screen). Ja FutureProvidera/Providera używam jedynie w miejscach w których coś chcę wyświetlić readonly(z pewnymi wyjątkami o których za chwilę**). U Ciebie w obu przypadkach, tj. widget do wyszukiwania i screen do wyświetlania listy dokumentów zachodzi jakaś interakcja, więc w przypadku listy dokumentów zdecydowałbym się na kontroler pod postacią StateNotifiera, natomiast w przypadku szukajki na app barze... to zależy. Jeżeli nie będziesz implementował sam całego zachowania searcha, tylko będziesz bazował na jakiej paczce z pub.dev która załatwi 99% logiki to imo nie ma sensu stosować tam StateNotifiera, bo to overkill, tylko zawrzeć ten 1% logiki w samym widgetcie po stronie UI. Jeżeli jednak byś chciał implementować sam całego searcha i jego zachowanie to zdecydowanie użyłbym StateNotifiera.

** czasem jeżeli widget jest reużywany w wielu miejscach i sam z siebie nigdzie nie jest używany, tylko ma sens będąc częścią czegoś, to unikam w ogóle stosowania riverpoda i udaje się w kierunku natywnych mechanizmów jak StreamListener, NotificationListener, FutureListener, etc. Stosuje tutaj podejście paczkowe. Paczki też nie mają zależności od riverpoda, bloca, czy innych state managementów.

0

Moim zdaniem najlepiej używać provider'a, jest recommended by Google i bardzo prosty bez boilerplate kodu.

0

@Descendant: Ok i ja chętnie spróbuje ale założe się, że przykładowe projekty i dokumentacja będzie na temat ToDo, a to mnie nie interesuje, ponieważ nie potrafię tego przełożyć na mój projekt, który ma obszernieszą logikę.

1

Również wolę providera. Fenomen riverpoda polega na tym, że autor biblioteki dostał błogosławieństwo od google'a odnośnie providera, a potem wykorzystał zdobytą popularność do wypromowania drugiej biblioteki.

Nie jest zły ale jest jednym z 10 innych state managerów..

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