2017-04-21 13 views
11

Zajmuję się tworzeniem projektu zgodnego z architekturą MVP. Zwykle, gdy używam recyclerView, mój prezenter kontroluje dane adaptera. Ale teraz muszę zrobić adapter do recyklingu z danymi z pamięci podręcznej (lub czymś podobnym do pamięci podręcznej), rozmiar recyklera nie zależy od rozmiaru pamięci podręcznej, więc robię cache za pomocą HashMap gdzie klucz jest - pozycja recyklera, jeśli jest w nim jakiś przedmiot mapa następnie pokazuje dane, w przeciwnym razie pusty wiersz z czymś w rodzaju "dodaj wydarzenia" btn. I nie mogę sobie przypomnieć, gdzie jest miejsce dla tej pamięci podręcznej w takiej strukturze - Model (Dao lub coś w rodzaju CacheManager) lub w adapterze.Pamięć danych adaptera MVP

Pomysł pamięci podręcznej jest następujący: Mam pewne typy zdarzeń, które przechowują w bazie danych, każde wydarzenie modyfikujące zmienia je w db - więc pamięć podręczna musi być aktualizowana.

Podstawowe pytania: gdzie zachować tę pamięć podręczną i załadować ją do adaptera, jak mogę ją synchronizować ze zmianami w bazie danych.

P.S. Również próbuję użyć RX, więc jeśli można go rozwiązać - byłoby bardzo interesujące spróbować.

P.P.S Jeśli wzór repozytorium jest sposobem rozwiązania - witamy. Przeczytaj o tym kiedyś.

Odpowiedz

3

Twój problem nie brzmi jak jest to związane z RecyclerView.Adapter - i rzeczywiście nie należy próbować go rozwiązać w swoim Adapter: odpowiedzialność adapter ma działać jako most (lub „adapter” ;-)) między danymi a komponentem widoku. Nadanie jej większej odpowiedzialności zamieniłoby ją w coś, co nie jest wymienne z innymi implementacjami Adapter (tego nie chcesz!).

Najprawdopodobniej powinieneś znaleźć czysty sposób na streszczenie utrwalania danych. Pamięć podręczna w pamięci powinna wchodzić w tę abstrakcję. Wspomniałeś o strukturze repozytorium, to byłby dobry wybór IMHO.

Twój architektura powinna z grubsza wyglądać tak:

adapter -> repository -> |-> cache 
         |-> database 

Repozytorium łączy logikę dostępu do danych (DAO) Twój i obsługi pamięci podręcznej (Twój CacheManager). Repozytorium zawsze najpierw sprawdza pamięć podręczną, a następnie pobiera dane z bazy danych. Aktualizuje także pamięć podręczną, jeśli pobierane są dane nieużywane w pamięci podręcznej. Ponadto rejestruje aktualizacje w bazie danych. Gdy baza danych powiadomi o zmianie danych, repozytorium ma szansę zaktualizować pamięć podręczną i/lub przekazać powiadomienie do widoku. Ważną częścią jest to, że interfejs repozytorium ukrywa całą tę logikę; zapewnia tylko dostęp do danych.

Następnie należy znaleźć sposób, aby adapter działał z repozytorium. Sugeruję mechanikę Androida: Loader. W ten sposób otrzymujesz asynchroniczne ładowanie i prawidłową obsługę cyklu życia za darmo. Również ten ładnie oddziela adapter i repozytorium.

Jeśli potrzebujesz inspiracji, jak zastosować wzór repozytorium, zajrzyj do github googlesamples/android-architecture. Model Clean Architecture branch może być dla Ciebie odpowiedni.

Na marginesie: spróbuj znaleźć prawdziwe (niepowtarzalne) klucze danych. Używanie pozycji na liście danych jest zwykle złym pomysłem i w zależności od struktury danych spowoduje dziwne efekty uboczne w widoku.

+0

Czy korzystanie z repozytorium z adaptera bez prezentera nie jest złe? Zaimplementowałem swoją pamięć podręczną w klasie DAO i nazwałem ją od Adaptora, ale "mam złe przeczucia". P.S. Mój klucz nie jest prostą pozycją, tylko zależy od pozycji. f (pozycja) = klucz – shagi

+0

Masz rację. Dlatego zaproponowałem używanie Ładowarki: (1) Twój prezenter zajmuje się ładowaczem (inicjalizacja, oddzwanianie wyników itp.); (2) moduł ładujący ładuje dane z repozytorium; (3) prezenter przyjmuje wywołanie zwrotne Loader i przekazuje dane do adaptera – Brian

+0

Ok zamiast Loadres używam Rx. Więc mam pomysł inicjalizacji, ale co z działaniami z ViewHolders? Czy powinienem utworzyć interfejs w moim adapterze, a następnie zaimplementować go w Fragment \ Activity lub Presenter oO? Czy istnieje lepszy sposób komunikacji? RxBus (EventBus)? – shagi

1

Myślę, że to temat architektury. Rx jest poza tematem. Na przykład dla repozytorium, Rx jest po prostu sposobem na jego wdrożenie, a przez to rozszerzenie jego pamięci podręcznej.

Repozytorium Google udostępnia przykłady architektury.Jeden z nich zawiera przykład architektury z podstawowym MVP i repozytorium którzy zarządzają cache:

googlesamples/android-architecture/todo-mvp

Innym przykładem w tym samym repozytorium z Rx:

googlesamples/android-architecture/todo-mvp-rxjava

Możemy być widać tutaj, że te dwa przykłady mają ten sam schemat architektury:

enter image description here

+0

tak, zrozumiałem ideę buforowania danych) Ostatnie pytanie, które nie jest dla mnie jasne, to jak podłączyć adapter i prezenter? Komentarz do poprzedniej odpowiedzi – shagi

+0

@shagi IMHO, w swoim prezenterie wywołujesz swoje repozytorium lub logikę biznesową, aby uzyskać dane (możesz użyć tutaj Rx). Prezenter wywołuje metodę z fragmentu do transmisji danych. Fragment implementuje adapter i jego logikę. Sesje interfejsu/fragmentu nasłuchują interfejsu użytkownika (można tutaj użyć Rx) i wywołują metodę prezentera. Prezenter zawiera logikę, aby zrobić coś po wydarzeniach interfejsu użytkownika. – compte14031879

+1

Szczegóły z tego samego przykładu dla Rx. Fragment i adapter (bez Rx tutaj użytego! Jeśli używasz tutaj rx, jest to dla zdarzeń interfejsu użytkownika): https://github.com/googlesamples/android-architecture/blob/todo-mvp-rxjava/todoapp/app/src/main /java/com/example/android/architecture/blueprints/todoapp/tasks/TasksFragment.java - Presenter (Rx używany tutaj do subskrybowania obserwatora repozytorium): https://github.com/googlesamples/android-architecture/blob/ todo-mvp-rxjava/todoapp/app/src/main/java/com/example/android/architektura/blueprints/todoapp/tasks/TasksPresenter.java – compte14031879