2

I am trying to implement recyclerview in a fragment using MVVM but the items are not loading on the screen. Here's the code:

BlankFragment.java:

package com.phunware.example.mvvmrecyclerviewblog;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.phunware.example.mvvmrecyclerviewblog.databinding.FragmentBlankBinding;
import com.phunware.example.mvvmrecyclerviewblog.viewmodel.DataViewModel;

import static android.support.v7.widget.LinearLayoutManager.VERTICAL;

public class BlankFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        FragmentBlankBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_blank, container, false);
        binding.setViewModel(new DataViewModel());

        binding.executePendingBindings();

        RecyclerView recyclerView = binding.getRoot().findViewById(R.id.data_recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
        recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), VERTICAL));

        new DataViewModel().setUp();

//       initRecyclerView(binding.getRoot());
        return binding.getRoot();
    }
}

fragment_blank.xml:

<layout xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="viewModel"
            type="com.phunware.example.mvvmrecyclerviewblog.viewmodel.DataViewModel"/>
    </data>

    <android.support.v7.widget.RecyclerView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/data_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/black"
        app:adapter="@{viewModel.adapter}"
        app:data="@{viewModel.data}"
        tools:context="com.phunware.example.mvvmrecyclerviewblog.view.MainActivity"/>
</layout>

DataViewModel.java:

package com.phunware.example.mvvmrecyclerviewblog.viewmodel;

import android.databinding.BaseObservable;
import android.databinding.Bindable;

import com.phunware.example.mvvmrecyclerviewblog.BR;
import com.phunware.example.mvvmrecyclerviewblog.adapter.DataAdapter;
import com.phunware.example.mvvmrecyclerviewblog.model.DataModel;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Gregory Rasmussen on 7/26/17.
 */
public class DataViewModel extends BaseObservable {
    private static final String TAG = "DataViewModel";
    private DataAdapter adapter;
    private List<DataModel> data;

    public DataViewModel() {
        data = new ArrayList<>();
        adapter = new DataAdapter();
    }

    public void setUp() {
        // perform set up tasks, such as adding listeners, data population, etc.
        populateData();
    }

    public void tearDown() {
        // perform tear down tasks, such as removing listeners
    }

    @Bindable
    public List<DataModel> getData() {
        return this.data;
    }

    @Bindable
    public DataAdapter getAdapter() {
        return this.adapter;
    }

    private void populateData() {
        // populate the data from the source, such as the database.
        for (int i = 0; i < 50; i++) {
            DataModel dataModel = new DataModel();
            dataModel.setTitle(String.valueOf(i));
            data.add(dataModel);
        }
        notifyPropertyChanged(BR.data);
    }
}

I have tried by calling the setup() from almost every lifecycle method of an Fragment but it is not working. If you want more project files then i can upload or you can watch the rest of the project file from this github repo. Please help me to solve this issue or any alternate way of implementing it would be accepted.

Edit: If we use this approach on an activity rather than a fragment then this code works fine which you can see in the original repo.

Raymond Chenon
  • 11,482
  • 15
  • 77
  • 110
sak
  • 1,230
  • 18
  • 37

2 Answers2

1

It worked by calling the setLayoutManager(..) before setting up the viewModel(...) and also one call of setAdapter() is also to be made. Here's the code of BlankFragment.java:

FragmentBlankBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_blank, container, false);

        RecyclerView recyclerView = binding.getRoot().findViewById(R.id.data_recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
        recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), VERTICAL));

        dataViewModel = new DataViewModel();
        binding.setViewModel(dataViewModel);

        binding.executePendingBindings();

        recyclerView.setAdapter(dataViewModel.getAdapter());
        dataViewModel.setUp();

        return binding.getRoot();

But the reason why this worked is still not known as the previous code works in the case of activities. If anyone knows then can edit this answer or can post another answer too.

Edit: As said by @Zubair this is the main reason why this didn't worked but the above solution is also working so both answers are correct.

sak
  • 1,230
  • 18
  • 37
1

first you did binded your data with this code

binding.setViewModel(new DataViewModel());

which doesn't get hold of the object created in with the new keyword then again you called

new DataViewModel().setUp();

so the binded viewModel object was something else and you called viewModel.setup(); on some other object hence you didnt get the data in the recyclerView

Zubair Soomro
  • 180
  • 1
  • 12