Skip to content

Commit

Permalink
✨ chore(README): add README.md with project information and setup ins…
Browse files Browse the repository at this point in the history
…tructions

Signed-off-by: Dmytro Turskyi <dmytro.turskyi@gmail.com>
  • Loading branch information
Turskyi committed Jul 25, 2024
1 parent 952f968 commit 25f2927
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 38 deletions.
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct-single.svg)](https://stand-with-ukraine.pp.ua)
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/Turskyi/TaskList">

# TaskList App

A sample Android application demonstrating the use of Android Room database
for task management.

## Features:

- Add tasks with high, middle, or low priority
- Delete tasks by swiping left or right
- Simple and intuitive interface
- **Code Readability:** code is easily readable with no unnecessary blank lines,
no unused variables
or methods, and no commented-out code, all variables, methods, and resource
IDs are descriptively
named such that another developer reading the code can easily understand their
function.

## Technologies Used:

- [Android](https://developer.android.com/studio/intro)
- [Kotlin](https://kotlinlang.org/)
- [Monolithic Architecture](https://en.wikipedia.org/wiki/Monolithic_architecture)
- AndroidX Room (room-ktx)
- View Model

## Getting Started:

1. Download the project
2. Open in Android Studio
3. Run on an emulator or Android device

## Usage:

- Use the app as a regular task manager
- Explore the code to learn about Android Room implementation

## Contributing:

Contributions are welcome! Create a pull request to the master branch.

## License:

No intentional license was used for this project.

## Contact:

Dmytro Turskyi

[dmytro@turskyi.com](mailto:dmytro@turskyi.com)

https://github.com/Turskyi

Note: Since this is a sample app, it's not intended for production use or
publication on Google Play.

## Screenshots:

<!--suppress CheckImageSize -->
<img src="screenshots/AddTaskScreenshot_20240724.png" width="200" alt="screenshot">
<img src="screenshots/tasks_Screenshot_20240724.png" width="200" alt="screenshot">
24 changes: 12 additions & 12 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ plugins {
}

android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
compileSdkVersion 34

defaultConfig {
applicationId "io.github.turskyi.tasklist"
minSdkVersion 21
targetSdkVersion 30
targetSdkVersion 34
versionCode 1
versionName "1.0"

Expand All @@ -31,29 +30,30 @@ android {
kotlinOptions {
jvmTarget = '1.8'
}
namespace 'io.github.turskyi.tasklist'
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.3'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.3'
implementation 'androidx.core:core-ktx:1.13.1'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.7.7'
implementation 'androidx.navigation:navigation-ui-ktx:2.7.7'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

/* Room DB */
def room_version = "2.2.6"
def room_version = "2.6.1"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"

// optional - Room Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'

// optional - Room Test helpers
testImplementation "androidx.room:room-testing:$room_version"
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.turskyi.tasklist">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:allowBackup="true"
Expand All @@ -11,6 +10,7 @@
android:theme="@style/Theme.TaskList">
<activity
android:name="io.github.turskyi.tasklist.presentation.features.main.view.MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.TaskList.NoActionBar">
<intent-filter>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.github.turskyi.tasklist.database

import android.content.Context
import android.util.Log
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
Expand All @@ -13,25 +12,19 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun taskDao(): TaskDao?

companion object {
private val LOG_TAG = AppDatabase::class.java.simpleName
private val LOCK = Any()
private const val DATABASE_NAME = "tasklist"
private var sInstance: AppDatabase? = null
fun getInstance(context: Context): AppDatabase {
if (sInstance == null) {
synchronized(LOCK) {
Log.d(
LOG_TAG,
"Creating new database instance"
)
sInstance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java, DATABASE_NAME
)
.build()
}
}
Log.d(LOG_TAG, "Getting the database instance")
return sInstance!!
}
}
Expand Down
13 changes: 9 additions & 4 deletions app/src/main/java/io/github/turskyi/tasklist/database/TaskDao.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package io.github.turskyi.tasklist.database

import androidx.lifecycle.LiveData
import androidx.room.*
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Update
import io.github.turskyi.tasklist.database.TaskEntry.Companion.TABLE_TASKS

@Dao
Expand All @@ -10,13 +15,13 @@ interface TaskDao {
fun loadAllTasks(): LiveData<List<TaskEntry>?>?

@Insert
fun insertTask(taskEntry: TaskEntry?)
fun insertTask(taskEntry: TaskEntry)

@Update(onConflict = OnConflictStrategy.REPLACE)
fun updateTask(taskEntry: TaskEntry?)
fun updateTask(taskEntry: TaskEntry)

@Delete
fun deleteTask(taskEntry: TaskEntry?)
fun deleteTask(taskEntry: TaskEntry)

@Query("SELECT * FROM $TABLE_TASKS WHERE id = :id")
fun loadTaskById(id: Int): LiveData<TaskEntry?>?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import io.github.turskyi.tasklist.database.AppDatabase

class AddTaskViewModelFactory(private val mDb: AppDatabase, private val mTaskId: Int) :
NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
return AddTaskViewModel(mDb, mTaskId) as T
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,15 @@ class MainActivity : AppCompatActivity(), ItemClickListener {
return false
}

/* Called when a user swipes left or right on a ViewHolder */
/* Called when a user swipes left or right on a ViewHolder. */
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {
/* implementation of swipe to delete */
/* Implementation of swipe to delete. */
AppExecutors.instance?.diskIO()?.execute {
val position = viewHolder.adapterPosition
val tasks: List<TaskEntry>? = mAdapter?.tasks
mDb?.taskDao()?.deleteTask(tasks?.get(position))
if (tasks != null) {
mDb?.taskDao()?.deleteTask(tasks[position])
}
}
}
}).attachToRecyclerView(mRecyclerView)
Expand Down Expand Up @@ -96,9 +98,9 @@ class MainActivity : AppCompatActivity(), ItemClickListener {

private fun setupViewModel() {
val viewModel: MainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
viewModel.tasks?.observe(this, { taskEntries ->
viewModel.tasks?.observe(this) { taskEntries ->
Log.d(TAG, "Updating list of tasks from LiveData in ViewModel")
mAdapter?.tasks = taskEntries
})
}
}
}
10 changes: 5 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.4.31"
ext.kotlin_version = "2.0.0"
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.2"
classpath 'com.android.tools.build:gradle:8.5.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

// NOTE: Do not place your application dependencies here; they belong
Expand All @@ -17,10 +17,10 @@ buildscript {
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}

task clean(type: Delete) {
tasks.register('clean', Delete) {
delete rootProject.buildDir
}
5 changes: 4 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
kotlin.code.style=official
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
Binary file added screenshots/AddTaskScreenshot_20240724.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/tasks_Screenshot_20240724.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 25f2927

Please sign in to comment.