6

I've an app that from now I have a list filled up from my api. Now I'm detecting the onClick on recyclerView and I want to open a GoogleMaps with a marker focused on the item I clicked (I have lat and long). Is there a good approach to do this with it's Repository, usecases, model, etc?

The thing is that I have on my ModelView is the coordinates where it is, and the type of cat, also the id.

The thing is that I do not know what to send to the other activity because everytime I make an api call the data changes, so I do not know if I have to store it anywhere and then show the data from listView and then create a refresh button on mapActivity where I can restart the data from api.

Hope you understand my problem.

An example that I'm following is this one : GitHub repository this is what I have as a list, then when clicking on an item it should open the map.

EDIT

I ended up passing the list when I click on an item from the List (If you have any other way please feel free to tell me)

Then I created a contract that it's :

interface Presenter{
        fun onMapReady()
    }

    interface View{
        fun focusOnItem(latitude: Double, longitude: Double)
        fun putMarkers(mList)
    }

Then I do not know where to use rxJava on my presenter, because I need to wait until I set stuff for my presenter like views and data and when I filled all up then start doing the putMarkers first, then focusOnItem, but I'm stuck on this.

So what I'm doing at the moment is from mapActivity I set the list and then I want to start doing the job.

TL;DR

Since start I had an activity (that is almost the same from the Github repo and then I need to pass the list to my other activity I ended up doing a setter to a presenter because dagger didn't know about that list so, my problem now is how do I set up all of the MVP with rxJava to load the map and load the markers on it. It should also zoom to the element clicked but I already have the location.

With a simple pseudo if you convince myself to do it this way I'll accept your answer as a correct, I just need to figure it out how to do this in rxJava.

StuartDTO
  • 783
  • 7
  • 26
  • 72

2 Answers2

2

You should not pass big amounts of data from one Activity to another, as you can easily reach the maximum amount that may be passed between them.

Instead, you should better save your data in your model classed for one Activity (for example, the one containing the list), and then pass only some item id to the other one. The second Activity (more precise, its presenter), should take the id and query the required object from the model.

Overall, the call chain will look like:

  1. Activity with list of items downloads this items when it is created. The download is initiated in ItemsListPresenter that calls Interactor/UseCase or directly a Repository.

  2. The downloaded items are cached in some way using the Repository.

  3. The downloaded items are displayed as a list in the View (in our case - Activity).
  4. When user clicks on item, this click is sent to ItemsListPresenter, and it sends a call to navigate to MapsView, passing the selected item id as a parameter.
  5. MapActivity is opened, the passed item id is taken.
  6. MapPresenter gets selected id in its constructor (or a setter)
  7. MapPresenter gets all the points from model (in our case using Interactor/UseCase or directly a Repository) and displays them.
  8. MapPresenter makes view to focus on a selected point (where the point is taken from model by its id)

As a result, we manage to open a screen that will contains all the points and it will be focused on the one selected by user.

You can find a simple Earthquakes app created based on the Clean Architecture approach and using MVP pattern and RxJava 2 here: https://github.com/Gaket/Earthquakes

Upd:

To be little more precise, you can do it like this (pseudocode):

class Presenter extends IPresenter {

   Model model;
   View view;
   List<Item> elements;
   Item selectedElement;

   void setSelectedItem(String id) {
      element = model.getElement(id);
   }

   void start() {
      // if you need to make an api call - do it here
      model.getElements().subscribe(elements -> this.elements = elements);
   }

   void onMapReady() {
      view.showElements(elements);
      view.focus(selectedElement);
   }
}

class MapActivity implements View {
    IPresenter presenter;

    void onCreate(...) {
        // start your map fragment
        String id = // get id from Intent
        presenter.setSelectedItem(id);
        presenter.start();
    }

    void putMarkers(List<Item> elements) {
        // put your markers as usual
    }

    void focusOnItem(Element element) {
        // and focus works the same. The only question is if you want to send an Element object here or particular coordinates. Both variants work.
    }

    @Override
    void onMapReady(GoogleMap map) {
         // save map
         presenter.onMapReady();
    }

}
Gaket
  • 6,533
  • 2
  • 37
  • 67
  • The problem is to use rxJava with GoogleMaps, that part is already developed, yes, you're right, we don't have to pass data from there, but if your api call is only to get stuff you can not get from id it's not good... – StuartDTO Nov 08 '18 at 20:04
  • What do you mean by "use rxJava with GoogleMaps"? Can you get some particular API examples that you want to use? – Gaket Nov 08 '18 at 20:23
  • Can you get an item by ID from your server? If you can, then you should be able to write usual Repository -> Cache -> API chain, so all the future requests will return you data from cache and not API if I get you correctly. And of course you can do it using RxJava. – Gaket Nov 08 '18 at 20:56
  • No I can not, but now I have a question, I have the method fillMarkersOnMap and I send to my activity the complete list, is there any other clean way to instad of sending all of the list and make the view work for instance do it in presenter? I have different type of images though... – StuartDTO Nov 08 '18 at 21:05
  • Yes, I suggested in the answer, when you get the list on the first activity, you can save it in some local storage, eg using Room. Then, when you open the details screen, you get that data from db, it will be quite fast. – Gaket Nov 08 '18 at 21:07
  • Yes, but for instance now I can not change it, I'll not your method ofc but my api is not good for this case so I have to send the full arrayList, the thing is can you provide an example with view and presenter to add the markers please? – StuartDTO Nov 08 '18 at 21:09
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/183323/discussion-between-gaket-and-stuartdto). – Gaket Nov 08 '18 at 21:24
0

So, I don't actually recommend people build things this way anymore (I now decouple the adapter from the view, and have the presenter coordinate both), but my newer samples are Kotlin + Coroutines so that probably won't help you.

Here is an old open source AlarmManager Application, which should hopefully demonstrate at least part of what you're looking for. I wasn't a pro with RxJava back then, so be wary that it might not be optimally made for error handling and memory management.

https://github.com/BracketCove/PosTrainer

Ryan
  • 762
  • 8
  • 17