androidgoogle-cloud-firestoreandroid-mvp

Firestore data extraction sequence in a MVP pattern in Android JAVA


I am new to MVP architect and I am implementing it in my App. I start with fetching the data from Firestore first and update an activity list to an adapter in a fragment.

I am having problem in the sequence on running the repository part in Firestore. I have set to run my Fetch data function first then do the update view to interface in the presenter. However, the result turn out it finish the update view first then Fetch the data. I am not sure what wrong is in my code.

I have my View

private ActivityAdapter ActivityAdapter;
ArrayList<Activity> ActivityList = new ArrayList<>();
private SpotDetailPresenter SpotPresenter;

@Override
public void onAttach(Context context) {
        super.onAttach(context);
        mContext=context;

}

public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
      Presenter = new Presenter(this);
      final View root = inflater.inflate(R.layout.fragment_activity_list, container, false);
      RecyclerView recyclerView = root.findViewById(R.id.rvContainer);
      Presenter.GetActivityList();
      recyclerView.setHasFixedSize(true);
      recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
      recyclerView.setAdapter(ActivityAdapter);
      return root;

}

@Override
public void UpdateActivityList(ArrayList<Activity> newActivityList) {


        for (int i = 0 ; i<newActivityList.size();i++){

            ActivityList.add(newActivityList.get(i));

        }
        ActivityAdapter = new ActivityAdapter(ActivityList, mContext);
        ActivityAdapter.notifyDataSetChanged();

}

My presenter

public class Presenter {

    private Repository Spot;
    private View view;
    public Presenter (View view) {

        this.Spot = new Repository();
        this.view = view;

    }

    public void GetActivityList(){
        Spot.getFullActivityList();
        view.UpdateActivityList(Spot.toArray());

    }


    public interface View{

        void UpdateActivityList(ArrayList<Activity> ActivityList);

    }

}

My Repository

public class Repository_Spot {

    private CollectionReference Ref = Helper.getCheckinCollection();

    private ArrayList<Activity> ActivityList = new ArrayList<>();


    public Repository (){

    }

    public Repository(ArrayList<Activity> ActivityList){
        this.ActivityList = ActivityList;

    }

    public void getFullActivityList(){

        Ref.document("uid").get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {

            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {

                if (task.isSuccessful()) {

                    DocumentSnapshot document = task.getResult();
                    Map<String, HashMap> root = (Map<String, HashMap>) document.get(Root);
                    this.ActivityList.add(new Activity(root.getValue()));

                }
            }

        });

    }

    public ArrayList<Activity> toArray(){

        return ActivityList;

    }

}

Based on above coding, it run the "Ref.document("uid").get()" part at last. As the result, I cannot refresh the view with the data. Any idea on what I do change? Am I having something wrong on my "Adapter.notifyDataSetChanged();"?


Solution

  • You are doing the callback wrong. Your firebase callback is basically another thread. Then it update data AFTER you call view.UpdateActivityList(). To fix this, you have to create a way to notify your Presenter that your Repo have the updated data. Then Presenter will update the View.

    1. public void GetActivityList(){
      Spot.getFullActivityList();
      view.UpdateActivityList(Spot.toArray()); -> Remove this. 
      

      }

    2. Create new interface inside your presenter to get update from your Repo:

      interface onDataUpdateListener(){

      void onDataUpdated(Your list);
      

      }

    3. Notify your presenter when repo completed task.

       @Override
          public void onComplete(@NonNull Task<DocumentSnapshot> task) {
      
              if (task.isSuccessful()) {
      
                  DocumentSnapshot document = task.getResult();
                  Map<String, HashMap> root = (Map<String, HashMap>) document.get(Root);
                  this.ActivityList.add(new Activity(root.getValue()));
               yourlisener.onDataUpdated(Your list)
             }
      
    4. Set listener when u init your Repo

      public Repository (Your listener){

      }

    5. Implement the listener inside your Presenter.

      Presenter implements onDataUpdateListener { }