0

I am trying to use MVVM, I am trying to get the data in my Viewodel ( normally coming from a service ) and set them to my activity, but it seems like it does not works, when I try just a simple ArrayList of ContractModel and add it to my adapters, everything works fine, but when I try to call my ViewModel things stops working.

I am folowing a course that is doing the same things as I did but not having the same result.

This is my MainActivity :

public class MainActivity extends AppCompatActivity {

    ContractsListViewModel contractsListViewModel;

    @BindView(R.id.contractList)
    RecyclerView contractList;

    RecyclerView.Adapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ButterKnife.bind(this);

        contractList.setLayoutManager(new LinearLayoutManager(this));

        contractsListViewModel = ViewModelProviders.of(this).get(ContractsListViewModel.class);
        contractsListViewModel.call();

        adapter = new ContractListAdapter(this, contractsListViewModel.contractList.getValue());

        contractList.setAdapter(adapter);

    }
}

That is my ViewModel :

public class ContractsListViewModel extends ViewModel {
   public MutableLiveData<List<ContractModel>> contractList;
   MutableLiveData<Boolean> isLoading;
   MutableLiveData<Boolean> error;

   public void call(){
    fetchContracts();
   }

   public void fetchContracts(){

    ContractModel contractModel = new ContractModel(1, "hfdfd", "h");
    ContractModel contractModel1 = new ContractModel(1, "hfdffddd", "h");
    ContractModel contractModel2 = new ContractModel(1, "hdffd", "j");
    ContractModel contractModel3 = new ContractModel(1, "hdffdfd", "h");

    List<ContractModel> list = new ArrayList<ContractModel>();

    list.add(...allofthem);

    contractList.setValue(list);

  }
}

My Adapter is working fine since it worked with the ArrayList I mentionned above. But here is :

public class ContractListAdapter extends RecyclerView.Adapter<ContractListAdapter.ContractViewHolder> {

    List<ContractModel> contracts;
    Context context;
    public ContractListAdapter(Context context, List<ContractModel> contracts){
        this.context = context;
        this.contracts = contracts;
    }

    @NonNull
    @Override
    public ContractViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.contrat, parent, false);
        return new ContractViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ContractViewHolder holder, int position) {
        holder.bind(contracts.get(position));
    }

    @Override
    public int getItemCount() {
        return this.contracts.size();
    }

    public class ContractViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.courtier)
        TextView courtier;

        public ContractViewHolder(@NonNull View view){
            super(view);
            ButterKnife.bind(this, view);
        }

        public void bind(ContractModel contractModel){
            courtier.setText(contractModel.getCourtier());
        }

    }
}

Any help would be much appreciated.

TaouBen
  • 1,165
  • 1
  • 15
  • 41

2 Answers2

1

I think Problem in your code is the reference of the list is changing again and again when the response comes and passed to the adapter, Though You have not posted code of your adapter, But I can assume You are overwriting the list reference in the adapter, what you should do Keep an ArrayList in the adapter since starting, when you pass the new list to the adapter, add items in the existing list and call notifyDataSetChanged(), so the adapter will have old reference to the list and will refresh new items in the recycler view. Representational code

Class MyAdapter extends RecycelerviewAdapter{

private List<ContractModel> globalList = new ArrayList();

public ( List<ContractModel> newlist){
globalList.addAll(newlist)
}

public updateList(List<ContractModel> newlist){
globalList.addAll(newlist)
}

}

And one thing I noticed also, You are not observing changes in livedata, so obviously next time when you fetch contract, you wont get any trigger point, when to refresh your adapter with notifyDataSetChanged.

So In your activity write something like this. I am writing pseudo code for understanding.

contractsListViewModel.contractList.observe{
adapter.updateList(newList);
adapter.notifydataSetCHanged()
}
akashzincle
  • 1,108
  • 6
  • 15
1

Quick fix

public MutableLiveData<List<ContractModel>> contractList=new MutableLiveData<>();

as you should create a list first before setting data to it here contractList.setValue(list);

more structured solution

public class ContractsListViewModel extends ViewModel {
public MutableLiveData<List<ContractModel>> contractList=new MutableLiveData<>();
MutableLiveData<Boolean> isLoading;
MutableLiveData<Boolean> error;

public void call(){
    fetchContracts();
}

public void fetchContracts(){

    ContractModel contractModel = new ContractModel(1, "hfdfd", "h");
    ContractModel contractModel1 = new ContractModel(1, "hfdffddd", "h");
    ContractModel contractModel2 = new ContractModel(1, "hdffd", "j");
    ContractModel contractModel3 = new ContractModel(1, "hdffdfd", "h");

    List<ContractModel> list = new ArrayList<ContractModel>();

    list.add(contractModel);
    list.add(contractModel1);
    list.add(contractModel2);
    list.add(contractModel3);


    contractList.postValue(list);

 }
}

MainActivity onCreate()

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ButterKnife.bind(this);

    contractList.setLayoutManager(new LinearLayoutManager(this));

    contractsListViewModel =  ViewModelProviders.of(this).get(ContractsListViewModel.class);
    contractsListViewModel.call();
    contractsListViewModel.contractList.observe(this,contractModels -> {
         adapter = new ContractListAdapter(MainActivity.this, contractModels);
         contractList.setAdapter(adapter);
    });

 }

check this to know difference between setValue & postValue

Mohammed Alaa
  • 3,140
  • 2
  • 19
  • 21