Android MVVM (JAVA)

1. view ( activity , fragments, adapter etc.)

2. view-model

3. repository (viewmodel collects data from here)

4. model (collect data from web server or local db.)

prerequisite

We will develop a simple note app.

prerequisite: basic knowledge of android development,such as

1. activity

2.recyclerview

3.adapter

4. paper database. (library for local nosql database )

Create Note Model class

Create a note class that has property called:

1.id

2.title

3.description

4.created_time

create a constructor and create getters and setters.

package com.m27lab.m27labnotemvvm.repository.models;

import java.util.Date;

public class NoteModel {
    private String id;
    private String title;
    private String description;
    private Date crated_time;

    public NoteModel(String id, String title, String description, Date crated_time) {
        this.id = id;
        this.title = title;
        this.description = description;
        this.crated_time = crated_time;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Date getCrated_time() {
        return crated_time;
    }

    public void setCrated_time(Date crated_time) {
        this.crated_time = crated_time;
    }
}

Create NoteDbRepository (repository) for the offline database we are going to use paper.io library

implementation 'io.paperdb:paperdb:2.6'

ok now create the repository:

1.create a singleton class to get the NoteDbRepository.class instance.

2.create a method to getAllNotes from the paper DB.

3.create two method for addNewNote / removeNote from paper DB.


** in getAllNotes() method we return list of note as a mutableLiveData object,so that we can edit it form our viewmodel.

package com.m27lab.m27labnotemvvm.repository.repos;

import android.content.Context;

import androidx.lifecycle.MutableLiveData;

import com.m27lab.m27labnotemvvm.repository.models.NoteModel;
import com.m27lab.m27labnotemvvm.define.Define;

import java.util.ArrayList;

import io.paperdb.Paper;

public class NoteDbRepository {
    private static final String NOTE_TABLE_KEY= Define.NOTE_TABLE_KEY;
    private ArrayList<NoteModel> noteList;
    private static NoteDbRepository mInstance;
    private static Context mCtx;

    private NoteDbRepository(Context context) {
        this.mCtx=context;
    }

    public static synchronized NoteDbRepository getInstance(Context context){
        if (mInstance == null) {
            mInstance = new NoteDbRepository(context);
        }
        return mInstance;
    }

    //get data from data source( offline db / from web service / fire-store db)
    public MutableLiveData<ArrayList<NoteModel>> getAllNotes(){
        //get data from paper
        loadNote();
        //make them mutable live data
        MutableLiveData<ArrayList<NoteModel>> mutableNoteList=new MutableLiveData<>();
        mutableNoteList.setValue(noteList);
        return mutableNoteList;
    }

    public void addNewNote(NoteModel note) {
        noteList.add(note);
        Paper.book().write(NOTE_TABLE_KEY,noteList);
    }

    public void removeNote(NoteModel note) {
        noteList.remove(note);
        Paper.book().write(NOTE_TABLE_KEY,noteList);
    }

    public void loadNote(){
        if(Paper.book().read(NOTE_TABLE_KEY)==null){
            noteList=new ArrayList<>();
        }else {
            noteList=Paper.book().read(NOTE_TABLE_KEY);
        }
    }

}

View Model

  1. create a class called HomeActivityViewModel
  2. this class will extends AndroidViewModel class or ViewModel class

2.1: if we extends from AndroidViewModel then we will get instance of Application class . but if we extends ViewModel we will not get instance of Application class .

3.create a repository object and retrieve all the note we have return from NoteDbRepository.class->getAllNotes() method. (we have done in inside init() method.)

4.create a method called getNoteList() that will return immutable(non-changeable ) notelist .what we will use in our view.so that nobody can edit these data from view.

5.create addNote() method that will call the repository addNewNote() method and add note to the paper database.

6.create deleteNote() method that will call the repository removeNote() method and remove note from the paper database.

package com.m27lab.m27labnotemvvm.viewmodels;

import android.app.Application;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import com.m27lab.m27labnotemvvm.repository.repos.NoteDbRepository;
import com.m27lab.m27labnotemvvm.repository.models.NoteModel;
import java.util.ArrayList;

public class HomeActivityViewModel extends AndroidViewModel {
    private Application application;
    private MutableLiveData<ArrayList<NoteModel>> allnotes;
    private NoteDbRepository noteRepo;

    public HomeActivityViewModel(@NonNull Application application) {
        super(application);
        this.application=application;
        init();
    }
    //init the repository
    private void init(){
        if(allnotes!=null){
            return;
        }//already we have retrieve the data
        noteRepo=NoteDbRepository.getInstance(application);
        allnotes=noteRepo.getAllNotes();
    }

    //get immutable live data
    public LiveData<ArrayList<NoteModel>> getNoteList(){
        return allnotes;
    }

    //insert new note
    public void addNote(NoteModel note){
        noteRepo.addNewNote(note);//added to the database
        ArrayList<NoteModel> updatedList=allnotes.getValue();//get
        allnotes.setValue(updatedList);

        Toast.makeText(getApplication().getApplicationContext(),"Added New Note.",Toast.LENGTH_SHORT).show();
    }
    //delete note
    public void deleteNote(NoteModel note){
        noteRepo.removeNote(note);//added to the database
        ArrayList<NoteModel> updatedList=allnotes.getValue();//get
        allnotes.setValue(updatedList);

        Toast.makeText(getApplication().getApplicationContext(),"Removed Note.",Toast.LENGTH_SHORT).show();
    }

}

View ( activity )

1. create a activity called HomeActivity. add a recyclerView and floating action button

2.find those using find view by ID.

//find view by id
noteListRV=findViewById(R.id.noteListRV);
addnote=findViewById(R.id.addnote);

3. initialized the paper database

//initialize paper DB
Paper.init(this);

4.initialized the view model
//init view-model
homeActivityViewModel=  new ViewModelProvider(this).get(HomeActivityViewModel.class);
5. get immutable notelist and set an observer to it. then override the method onChanged and call
adapter.notifyDataSetChanged();

6.setup the recyclerView ,i have used a method to separate the code
initRecyclerView();
 
 
package com.m27lab.m27labnotemvvm.views.activity;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.view.View;
import android.widget.HeaderViewListAdapter;
import android.widget.Toast;

import com.github.clans.fab.FloatingActionButton;
import com.m27lab.m27labnotemvvm.R;
import com.m27lab.m27labnotemvvm.helpers.getRandomString;
import com.m27lab.m27labnotemvvm.repository.models.NoteModel;
import com.m27lab.m27labnotemvvm.viewmodels.HomeActivityViewModel;
import com.m27lab.m27labnotemvvm.views.adapters.NotesListAdapter;

import java.util.ArrayList;
import java.util.Date;

import io.paperdb.Paper;

public class HomeActivity extends AppCompatActivity {
    private HomeActivityViewModel homeActivityViewModel;
    private RecyclerView noteListRV;
    private FloatingActionButton addnote;
    private NotesListAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        //find view by id
        noteListRV=findViewById(R.id.noteListRV);
        addnote=findViewById(R.id.addnote);

        //init paper
        Paper.init(this);

        //init view-model
        homeActivityViewModel=  new ViewModelProvider(this).get(HomeActivityViewModel.class);
        homeActivityViewModel.getNoteList().observe(this, new Observer<ArrayList<NoteModel>>() {
            @Override
            public void onChanged(ArrayList<NoteModel> noteList) {
                Toast.makeText(getApplicationContext(),"okkk",Toast.LENGTH_SHORT).show();
                //update recycler view
                //adapter.setNoteList(noteList);
                adapter.notifyDataSetChanged();
            }
        });

        initRecyclerView();

        addnote.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                NoteModel note=new NoteModel("1","title:","description",new Date());
                homeActivityViewModel.addNote(note);
            }
        });

    }//onCreate

    private void initRecyclerView() {
        adapter=new NotesListAdapter(this,homeActivityViewModel.getNoteList().getValue());
        noteListRV.setLayoutManager(new LinearLayoutManager(this));
        noteListRV.setAdapter(adapter);

    }//initRecyclerView

    public HomeActivityViewModel getViewModel(){
        return homeActivityViewModel;
    }
}

View ( adapter)

1.create a recycler view adapter.

2. if you want to delete a note of edit a note then implement onclickListener inside adapter

3.for deleting the note you need ViewModel that’s why create a method inside Activity and get the viewmodel…

HomeActivityViewModel vm=((HomeActivity)context).getViewModel();
//delete using viewmodel object
vm.deleteNote(noteList.get(position));

4.rest of the thing are same as normal adapter.


package com.m27lab.m27labnotemvvm.views.adapters;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.m27lab.m27labnotemvvm.R;
import com.m27lab.m27labnotemvvm.repository.models.NoteModel;
import com.m27lab.m27labnotemvvm.viewmodels.HomeActivityViewModel;
import com.m27lab.m27labnotemvvm.views.activity.HomeActivity;

import java.text.SimpleDateFormat;
import java.util.ArrayList;

public class NotesListAdapter extends RecyclerView.Adapter<NotesListAdapter.NoteViewHolder>{
    private Context context;
    private ArrayList<NoteModel> noteList;

    public NotesListAdapter(Context context,ArrayList<NoteModel> noteList) {
        this.noteList = noteList;
        this.context = context;
    }//Constructor

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

    @Override
    public void onBindViewHolder(@NonNull NoteViewHolder holder, final int position) {
        holder.notetitle.setText(noteList.get(position).getTitle());
        holder.noteDesc.setText(noteList.get(position).getDescription());
        holder.dateview.setText(new SimpleDateFormat("dd-MM-YYYY").format(noteList.get(position).getCrated_time()));
        holder.delete_note.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                deleteNote(position);
            }
        });
    }//onBindViewHolder

    private void deleteNote(int position) {
        HomeActivityViewModel vm=((HomeActivity)context).getViewModel();
        vm.deleteNote(noteList.get(position));
    }//deleteNote

    @Override
    public int getItemCount() {
        return noteList.size();
    }//getItemCount

     //view holder class
     class NoteViewHolder extends RecyclerView.ViewHolder {
        TextView notetitle,noteDesc,dateview;
        ImageView edit_note,delete_note;
        public NoteViewHolder(@NonNull View itemView) {
            super(itemView);
            notetitle=itemView.findViewById(R.id.notetitle);
            noteDesc=itemView.findViewById(R.id.description);
            dateview=itemView.findViewById(R.id.dateview);
            edit_note=itemView.findViewById(R.id.edit_note);
            delete_note=itemView.findViewById(R.id.delete_note);
        }
    }

//    ===================delete edit note...

}


Author: joker

Leave a Reply

Your email address will not be published. Required fields are marked *