Skip to content

Instantly share code, notes, and snippets.

@anantyan
Created August 22, 2023 06:22
Show Gist options
  • Save anantyan/26808353f6fcb76fc10c7bd2c5caae9d to your computer and use it in GitHub Desktop.
Save anantyan/26808353f6fcb76fc10c7bd2c5caae9d to your computer and use it in GitHub Desktop.
Membagikan mengenai implementasi sebuah code pemrograman menggunakan MVVM + Clean Architecture pada studi kasus penyimpanan database menggunakan ROOM Database untuk Notepad
// 4. Room Database (Data Layer)
@Database(entities = [Note::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun noteDao(): NoteDao
}
// 1. Model (Entity untuk Room) (Domain Layer)
@Entity(tableName = "notes")
data class Note(
@PrimaryKey(autoGenerate = true) val id: Int = 0,
val title: String = "",
val content: String = ""
)
// 7. Dagger Hilt Module
@Module
@InstallIn(SingletonComponent::class)
object RoomModule {
@Provides
@Singleton
fun provideDatabase(@ApplicationContext context: Context): AppDatabase {
return Room.databaseBuilder(
context,
AppDatabase::class.java, "app-database"
).build()
}
@Provides
fun provideNoteDao(database: AppDatabase): NoteDao {
return database.noteDao()
}
@Provides
@Singleton
fun provideNotesRepository(noteDao: NoteDao): NotesRepository = RoomNotesRepository(noteDao)
}
// 3. Dao (Data Access Object) (Data Layer)
@Dao
interface NoteDao {
@Query("SELECT * FROM notes")
fun getNotes(): Flow<List<Note>>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun addNote(note: Note): Long
@Update
suspend fun updateNote(note: Note)
@Delete
suspend fun deleteNote(note: Note)
}
// 5. Repository Interface (Domain Layer)
interface NotesRepository {
fun getNotes(): Flow<Resource>
suspend fun addNote(note: Note): Resource
suspend fun updateNote(note: Note): Resource
suspend fun deleteNote(note: Note): Resource
}
// 11. UI (Activity/Fragment) - a brief snippet
@AndroidEntryPoint
class NotesActivity : AppCompatActivity() {
private val viewModel: NoteViewModel by viewModels()
// ... rest of the code ...
viewModel.notesState.observe(this, Observer { state ->
when (state) {
is NoteState.Loading -> { /* ... */ }
is NoteState.Success -> { /* ... */ }
is NoteState.Error -> { /* ... */ }
}
})
}
// 10. ViewModel (Presentation Layer)
@HiltViewModel
class NoteViewModel @Inject constructor(
private val getNotesUseCase: GetNotesUseCase
// ... other use cases ...
) : ViewModel() {
val notesState: LiveData<NoteState> = getNotesUseCase.invoke().asLiveData()
// ... other methods ...
}
// 8. Sealed Class for State
sealed class NoteState {
object Loading : NoteState()
data class Success(val data: List<Note>) : NoteState()
data class Error(val exception: Throwable) : NoteState()
}
// 6. Repository Implementation (Data Layer)
class RoomNotesRepository @Inject constructor(private val noteDao: NoteDao) : NotesRepository {
override fun getNotes(): Flow<Resource> = flow {
emit(Resource.Loading)
try {
val notes = noteDao.getNotes().first()
emit(Resource.Success(notes))
} catch (e: Exception) {
emit(Resource.Error(e))
}
}
// ... other methods ...
}
// 9. Use Case (Use Case Layer)
class GetNotesUseCase @Inject constructor(private val repository: NotesRepository) {
fun invoke(): Flow<NoteState> {
return repository.getNotes()
}
}
// ... other Use Cases ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment