Dedicated Server

Building a Notes App for Android(Kotlin) using MVVM Architecture, Koin DI, and Room Library

Notes App for Android with Kotlin, MVVM, Koin DI, and Room

1. Create a new Android project

Create a new Android project in Android Studio with the package name com.example.buildianotes.

2. Set up dependencies

Set up the necessary dependencies in the build.gradle files.

Top-level build.gradle


buildscript {
    ext.kotlin_version = '1.5.21'
    // Add other dependencies if needed
}

allprojects {
    repositories {
        // Add necessary repositories
        google()
        jcenter()
    }
}
  

App-level build.gradle


plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt'
}

android {
    compileSdkVersion 30
    defaultConfig {
        applicationId "com.example.buildianotes"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    // Add necessary configurations

    buildTypes {
        release {
            // Add necessary configurations
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

    // Room
    implementation "androidx.room:room-runtime:2.4.0"
    kapt "androidx.room:room-compiler:2.4.0"

    // Koin
    implementation "org.koin:koin-androidx-viewmodel:3.2.0"

    // Add other necessary dependencies
}
  

3. Create the data model

Create the data model for the Note entity. Create a new Kotlin class called Note in the com.example.buildianotes.model package.


package com.example.buildianotes.model

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "notes")
data class Note(
    @PrimaryKey(autoGenerate = true) val id: Long = 0,
    val title: String,
    val content: String
)
  

4. Create the Room DAO

Create a new Kotlin file called NotesDao in the com.example.buildianotes.data package for defining the Room DAO (Data Access Object) interface.


package com.example.buildianotes.data

import androidx.lifecycle.LiveData
import androidx.room.*

@Dao
interface NotesDao {
    @Query("SELECT * FROM notes")
    fun getAllNotes(): LiveData<List<Note>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertOrUpdate(note: Note)

    @Delete
    suspend fun delete(note: Note)
}
  

5. Create the Room database

Create a new Kotlin file called NotesDatabase in the com.example.buildianotes.data package to define the Room database.


package com.example.buildianotes.data

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.example.buildianotes.model.Note

@Database(entities = [Note::class], version = 1)
abstract class NotesDatabase : RoomDatabase() {
    abstract fun notesDao(): NotesDao

    companion object {
        @Volatile
        private var INSTANCE: NotesDatabase? = null

        fun getInstance(context: Context): NotesDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    NotesDatabase::class.java,
                    "notes_database"
                ).build()
                INSTANCE = instance
                instance
            }
        }
    }
}
  

6. Create the data repository

Create a new Kotlin file called NotesRepository in the com.example.buildianotes.data package to handle data operations.


package com.example.buildianotes.data

import androidx.lifecycle.LiveData
import com.example.buildianotes.model.Note

class NotesRepository(private val notesDao: NotesDao) {
    val allNotes: LiveData<List<Note>> = notesDao.getAllNotes()

    suspend fun insertOrUpdate(note: Note) {
        notesDao.insertOrUpdate(note)
    }

    suspend fun delete(note: Note) {
        notesDao.delete(note)
    }
}
  

7. Create the ViewModel

Create a new Kotlin file called NotesViewModel in the com.example.buildianotes.viewmodel package to implement the ViewModel.


package com.example.buildianotes.viewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.buildianotes.data.NotesRepository
import com.example.buildianotes.model.Note
import kotlinx.coroutines.launch

class NotesViewModel(private val notesRepository: NotesRepository) : ViewModel() {
    val allNotes: LiveData<List<Note>> = notesRepository.allNotes

    fun insertOrUpdate(note: Note) {
        viewModelScope.launch {
            notesRepository.insertOrUpdate(note)
        }
    }

    fun delete(note: Note) {
        viewModelScope.launch {
            notesRepository.delete(note)
        }
    }
}
  

8. Set up dependency injection with Koin

Create a new Kotlin file called AppModule in the com.example.buildianotes.di package to define the dependency injection with Koin.


package com.example.buildianotes.di

import com.example.buildianotes.data.NotesDatabase
import com.example.buildianotes.data.NotesRepository
import com.example.buildianotes.viewmodel.NotesViewModel
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module

val appModule = module {
    single { NotesDatabase.getInstance(get()) }
    single { get<NotesDatabase>().notesDao() }
    single { NotesRepository(get()) }
    viewModel { NotesViewModel(get()) }
}
  

9. Initialize Koin in the Application class

In your Application class, initialize Koin with the AppModule in the onCreate() method. Create a new Kotlin file called NotesApp in the com.example.buildianotes package.


package com.example.buildianotes

import android.app.Application
import com.example.buildianotes.di.appModule
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.startKoin

class NotesApp : Application() {
    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidContext(this@NotesApp)
            modules(appModule)
        }
    }
}
  

10. Create the UI for displaying and managing notes

Create an activity or fragment for displaying and managing the notes. For example, create a new Kotlin file called NotesActivity in the com.example.buildianotes.ui package.


package com.example.buildianotes.ui

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.buildianotes.R
import com.example.buildianotes.model.Note
import com.example.buildianotes.viewmodel.NotesViewModel
import kotlinx.android.synthetic.main.activity_notes.*
import org.koin.androidx.viewmodel.ext.android.viewModel

class NotesActivity : AppCompatActivity() {
    private val notesViewModel: NotesViewModel by viewModel()
    private val notesAdapter = NotesAdapter()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_notes)

        setupRecyclerView()
        observeNotes()

        fabAddNote.setOnClickListener {
            // Handle click event to add a new note
        }
    }

    private fun setupRecyclerView() {
        rvNotes.apply {
            layoutManager = LinearLayoutManager(this@NotesActivity)
            adapter = notesAdapter
        }
    }

    private fun observeNotes() {
        notesViewModel.allNotes.observe(this, Observer { notes ->
            notesAdapter.submitList(notes)
        })
    }
}
  

11. Create the RecyclerView adapter

Finally, create the NotesAdapter class to handle the RecyclerView in the com.example.buildianotes.ui package.


package com.example.buildianotes.ui

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.buildianotes.R
import com.example.buildianotes.model.Note
import kotlinx.android.synthetic.main.item_note.view.*

class NotesAdapter : ListAdapter<Note, NotesAdapter.NoteViewHolder>(NoteDiffCallback()) {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoteViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_note, parent, false)
        return NoteViewHolder(view)
    }

    override fun onBindViewHolder(holder: NoteViewHolder, position: Int) {
        val note = getItem(position)
        holder.bind(note)
    }

    inner class NoteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(note: Note) {
            itemView.tvTitle.text = note.title
            itemView.tvContent.text = note.content
        }
    }

    class NoteDiffCallback : DiffUtil.ItemCallback<Note>() {
        override fun areItemsTheSame(oldItem: Note, newItem: Note): Boolean {
            return oldItem.id == newItem.id
        }

        override fun areContentsTheSame(oldItem: Note, newItem: Note): Boolean {
            return oldItem == newItem
        }
    }
}
  

Conclusion

Congratulations! You have successfully created a Notes app for Android using Kotlin, MVVM architecture, Koin DI, and Room. This app allows you to store and manage notes using a local database.

Feel free to customize the app further by adding more features, such as editing and deleting notes, adding labels or categories, implementing search functionality, and adding authentication.

No comments:

Post a Comment