Encapsulation in different layers of multiple datasources with MediatorLiveData

Multi tool use
Multi tool use












0














can anyone explain me how to design the different layers of an android app with a MediatorLiveData?



I have the following concrete problem: I'm getting a list of appointments (with a start- and enddate) out of my (Room-)database in form of LiveData. In my view, I want to display the appointments in a normalized way, i.e. the height of the appointments depends on the duration and there should be "whitespace" between two appointments, if the following doesn't start at the enddate of the first appointment.



As a second feature the calendar in my view should only begin with the greatest integer hour, that is smaller than or equals to the earliest appointment in a set of appointments for several days. So I'm getting another LiveData out of my database, that contains a Calendar-object with the earliest startdate of the appointments in the specified period.



I'm now confused about the best design with the different abstraction layers.



At the data layer I've a DAO with the following methods:
@Dao
abstract class AppointmentDao {
//Loads the appointments in the specified period:
abstract LiveData> getAppointmentsInPeriod(String startDate, String endDate);



   //Returns the minimum starttime of appointments in a specificed period:
abstract LiveData<Calendar> getEarliestBeginning(String startDate, String endDate);
}


As different android guides recommend, I created a repository layer, that just forwards the LiveDatas from the DAO.



I'm struggling now at the ViewModel. Here I have to load the appointments and fill the gaps between them.
But the list of appointments, that should go to the view depends on the list from the repository as well as on the earliest beginning.
So I think, it would be the best way to merge these LiveDatas in a MediatorLiveData, that is forwarded to the view.



So my approach was:



public AppointmentViewModel extends AndroidViewModel {
AppRepository repository;

LiveData<List<Appointment>> appointmentsFromDatabase;
LiveData<Calendar> earliestBeginning;

LiveData<List<Appointment>> appointmentsForView;

public AppointmentViwModel(Application app) {
repository = new AppRepository(app);

appointmentsForView = new MediatorLiveData();
appointmentsForView.addSource(appointmentsFromDatabase, appointments -> {
if(earliestBeginning != null && earliestBeginning.getValue() != null)
appointmentsForView = fillList(appointments, earliestBeginning.getValue());
});

appointmentsForView.addSource(earliestBeginning, beginning -> {
if(appointmentsFromDatabase != null && appointmentsFromDatabase.getValue() != null && !appointmentsFromDatabase.getValue().isEmpty())
appointmentsForView = fillList(appointmentsFromDatabase.getValue(), beginning);
});
}

public LiveData<List<Appointment>> getAppointmentsInPeriod(String startDate, String endDate) {
appointmentsFromDatabase = repository.getAppointmentsInPeriod(startDate, endDate);
earliestBeginning = repository.getEarliestBeginning(startDate, endDate);

return appointmentsForView;
}

private static LiveData<List<Appointment>> fillList(List<Appointment> appointments, Calendar beginning) {
//Fills the gaps in the given list
}
}


I don't actually know, where I have to check a null-reference and an empty collection, because I got so much Exceptions while programming, that I'm always checking on this stuff.



My doubts are in the handling of the MediatorLiveData. In the constructor it points to the class-variables, that are not inititalized, because they need some input values, that are fetched from the view, that calls the getAppointmentsInPeriod-method. But this method overwrites the objects every time, it is called.



So maybe someone can explain me the best practice of this design (pattern).



Thank you very much!










share|improve this question





























    0














    can anyone explain me how to design the different layers of an android app with a MediatorLiveData?



    I have the following concrete problem: I'm getting a list of appointments (with a start- and enddate) out of my (Room-)database in form of LiveData. In my view, I want to display the appointments in a normalized way, i.e. the height of the appointments depends on the duration and there should be "whitespace" between two appointments, if the following doesn't start at the enddate of the first appointment.



    As a second feature the calendar in my view should only begin with the greatest integer hour, that is smaller than or equals to the earliest appointment in a set of appointments for several days. So I'm getting another LiveData out of my database, that contains a Calendar-object with the earliest startdate of the appointments in the specified period.



    I'm now confused about the best design with the different abstraction layers.



    At the data layer I've a DAO with the following methods:
    @Dao
    abstract class AppointmentDao {
    //Loads the appointments in the specified period:
    abstract LiveData> getAppointmentsInPeriod(String startDate, String endDate);



       //Returns the minimum starttime of appointments in a specificed period:
    abstract LiveData<Calendar> getEarliestBeginning(String startDate, String endDate);
    }


    As different android guides recommend, I created a repository layer, that just forwards the LiveDatas from the DAO.



    I'm struggling now at the ViewModel. Here I have to load the appointments and fill the gaps between them.
    But the list of appointments, that should go to the view depends on the list from the repository as well as on the earliest beginning.
    So I think, it would be the best way to merge these LiveDatas in a MediatorLiveData, that is forwarded to the view.



    So my approach was:



    public AppointmentViewModel extends AndroidViewModel {
    AppRepository repository;

    LiveData<List<Appointment>> appointmentsFromDatabase;
    LiveData<Calendar> earliestBeginning;

    LiveData<List<Appointment>> appointmentsForView;

    public AppointmentViwModel(Application app) {
    repository = new AppRepository(app);

    appointmentsForView = new MediatorLiveData();
    appointmentsForView.addSource(appointmentsFromDatabase, appointments -> {
    if(earliestBeginning != null && earliestBeginning.getValue() != null)
    appointmentsForView = fillList(appointments, earliestBeginning.getValue());
    });

    appointmentsForView.addSource(earliestBeginning, beginning -> {
    if(appointmentsFromDatabase != null && appointmentsFromDatabase.getValue() != null && !appointmentsFromDatabase.getValue().isEmpty())
    appointmentsForView = fillList(appointmentsFromDatabase.getValue(), beginning);
    });
    }

    public LiveData<List<Appointment>> getAppointmentsInPeriod(String startDate, String endDate) {
    appointmentsFromDatabase = repository.getAppointmentsInPeriod(startDate, endDate);
    earliestBeginning = repository.getEarliestBeginning(startDate, endDate);

    return appointmentsForView;
    }

    private static LiveData<List<Appointment>> fillList(List<Appointment> appointments, Calendar beginning) {
    //Fills the gaps in the given list
    }
    }


    I don't actually know, where I have to check a null-reference and an empty collection, because I got so much Exceptions while programming, that I'm always checking on this stuff.



    My doubts are in the handling of the MediatorLiveData. In the constructor it points to the class-variables, that are not inititalized, because they need some input values, that are fetched from the view, that calls the getAppointmentsInPeriod-method. But this method overwrites the objects every time, it is called.



    So maybe someone can explain me the best practice of this design (pattern).



    Thank you very much!










    share|improve this question



























      0












      0








      0







      can anyone explain me how to design the different layers of an android app with a MediatorLiveData?



      I have the following concrete problem: I'm getting a list of appointments (with a start- and enddate) out of my (Room-)database in form of LiveData. In my view, I want to display the appointments in a normalized way, i.e. the height of the appointments depends on the duration and there should be "whitespace" between two appointments, if the following doesn't start at the enddate of the first appointment.



      As a second feature the calendar in my view should only begin with the greatest integer hour, that is smaller than or equals to the earliest appointment in a set of appointments for several days. So I'm getting another LiveData out of my database, that contains a Calendar-object with the earliest startdate of the appointments in the specified period.



      I'm now confused about the best design with the different abstraction layers.



      At the data layer I've a DAO with the following methods:
      @Dao
      abstract class AppointmentDao {
      //Loads the appointments in the specified period:
      abstract LiveData> getAppointmentsInPeriod(String startDate, String endDate);



         //Returns the minimum starttime of appointments in a specificed period:
      abstract LiveData<Calendar> getEarliestBeginning(String startDate, String endDate);
      }


      As different android guides recommend, I created a repository layer, that just forwards the LiveDatas from the DAO.



      I'm struggling now at the ViewModel. Here I have to load the appointments and fill the gaps between them.
      But the list of appointments, that should go to the view depends on the list from the repository as well as on the earliest beginning.
      So I think, it would be the best way to merge these LiveDatas in a MediatorLiveData, that is forwarded to the view.



      So my approach was:



      public AppointmentViewModel extends AndroidViewModel {
      AppRepository repository;

      LiveData<List<Appointment>> appointmentsFromDatabase;
      LiveData<Calendar> earliestBeginning;

      LiveData<List<Appointment>> appointmentsForView;

      public AppointmentViwModel(Application app) {
      repository = new AppRepository(app);

      appointmentsForView = new MediatorLiveData();
      appointmentsForView.addSource(appointmentsFromDatabase, appointments -> {
      if(earliestBeginning != null && earliestBeginning.getValue() != null)
      appointmentsForView = fillList(appointments, earliestBeginning.getValue());
      });

      appointmentsForView.addSource(earliestBeginning, beginning -> {
      if(appointmentsFromDatabase != null && appointmentsFromDatabase.getValue() != null && !appointmentsFromDatabase.getValue().isEmpty())
      appointmentsForView = fillList(appointmentsFromDatabase.getValue(), beginning);
      });
      }

      public LiveData<List<Appointment>> getAppointmentsInPeriod(String startDate, String endDate) {
      appointmentsFromDatabase = repository.getAppointmentsInPeriod(startDate, endDate);
      earliestBeginning = repository.getEarliestBeginning(startDate, endDate);

      return appointmentsForView;
      }

      private static LiveData<List<Appointment>> fillList(List<Appointment> appointments, Calendar beginning) {
      //Fills the gaps in the given list
      }
      }


      I don't actually know, where I have to check a null-reference and an empty collection, because I got so much Exceptions while programming, that I'm always checking on this stuff.



      My doubts are in the handling of the MediatorLiveData. In the constructor it points to the class-variables, that are not inititalized, because they need some input values, that are fetched from the view, that calls the getAppointmentsInPeriod-method. But this method overwrites the objects every time, it is called.



      So maybe someone can explain me the best practice of this design (pattern).



      Thank you very much!










      share|improve this question















      can anyone explain me how to design the different layers of an android app with a MediatorLiveData?



      I have the following concrete problem: I'm getting a list of appointments (with a start- and enddate) out of my (Room-)database in form of LiveData. In my view, I want to display the appointments in a normalized way, i.e. the height of the appointments depends on the duration and there should be "whitespace" between two appointments, if the following doesn't start at the enddate of the first appointment.



      As a second feature the calendar in my view should only begin with the greatest integer hour, that is smaller than or equals to the earliest appointment in a set of appointments for several days. So I'm getting another LiveData out of my database, that contains a Calendar-object with the earliest startdate of the appointments in the specified period.



      I'm now confused about the best design with the different abstraction layers.



      At the data layer I've a DAO with the following methods:
      @Dao
      abstract class AppointmentDao {
      //Loads the appointments in the specified period:
      abstract LiveData> getAppointmentsInPeriod(String startDate, String endDate);



         //Returns the minimum starttime of appointments in a specificed period:
      abstract LiveData<Calendar> getEarliestBeginning(String startDate, String endDate);
      }


      As different android guides recommend, I created a repository layer, that just forwards the LiveDatas from the DAO.



      I'm struggling now at the ViewModel. Here I have to load the appointments and fill the gaps between them.
      But the list of appointments, that should go to the view depends on the list from the repository as well as on the earliest beginning.
      So I think, it would be the best way to merge these LiveDatas in a MediatorLiveData, that is forwarded to the view.



      So my approach was:



      public AppointmentViewModel extends AndroidViewModel {
      AppRepository repository;

      LiveData<List<Appointment>> appointmentsFromDatabase;
      LiveData<Calendar> earliestBeginning;

      LiveData<List<Appointment>> appointmentsForView;

      public AppointmentViwModel(Application app) {
      repository = new AppRepository(app);

      appointmentsForView = new MediatorLiveData();
      appointmentsForView.addSource(appointmentsFromDatabase, appointments -> {
      if(earliestBeginning != null && earliestBeginning.getValue() != null)
      appointmentsForView = fillList(appointments, earliestBeginning.getValue());
      });

      appointmentsForView.addSource(earliestBeginning, beginning -> {
      if(appointmentsFromDatabase != null && appointmentsFromDatabase.getValue() != null && !appointmentsFromDatabase.getValue().isEmpty())
      appointmentsForView = fillList(appointmentsFromDatabase.getValue(), beginning);
      });
      }

      public LiveData<List<Appointment>> getAppointmentsInPeriod(String startDate, String endDate) {
      appointmentsFromDatabase = repository.getAppointmentsInPeriod(startDate, endDate);
      earliestBeginning = repository.getEarliestBeginning(startDate, endDate);

      return appointmentsForView;
      }

      private static LiveData<List<Appointment>> fillList(List<Appointment> appointments, Calendar beginning) {
      //Fills the gaps in the given list
      }
      }


      I don't actually know, where I have to check a null-reference and an empty collection, because I got so much Exceptions while programming, that I'm always checking on this stuff.



      My doubts are in the handling of the MediatorLiveData. In the constructor it points to the class-variables, that are not inititalized, because they need some input values, that are fetched from the view, that calls the getAppointmentsInPeriod-method. But this method overwrites the objects every time, it is called.



      So maybe someone can explain me the best practice of this design (pattern).



      Thank you very much!







      android android-livedata






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 27 at 14:02









      Fantômas

      32.3k156288




      32.3k156288










      asked Dec 27 at 13:23









      Naryxus

      11




      11





























          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53945827%2fencapsulation-in-different-layers-of-multiple-datasources-with-mediatorlivedata%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53945827%2fencapsulation-in-different-layers-of-multiple-datasources-with-mediatorlivedata%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          SnCBUs,zjJaRS8gxtkAWztWMFTN l
          OkWAmZgua0M6egZGCDThBvpZO1tmf O WDOERzfvlFdbkYEt2YqettzEUqoSxbPEhSeOpkuIxi dJ7sntjCnRCckFc0dvL,7Ry66

          Popular posts from this blog

          Monofisismo

          Angular Downloading a file using contenturl with Basic Authentication

          Olmecas