Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import java.util.Properties

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)

}


fun getApiKey(): String {
val properties = Properties()
val localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
localPropertiesFile.inputStream().use { properties.load(it) }
}
return properties.getProperty("API_KEY") ?: ""
}

android {
Expand All @@ -13,6 +26,8 @@ android {
targetSdk = 34
versionCode = 1
versionName = "1.0"
buildConfigField("String", "API_KEY", "\"${getApiKey()}\"")


testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
Expand All @@ -27,6 +42,12 @@ android {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
viewBinding {
enable = true
}
buildFeatures{
buildConfig=true
}
kotlinOptions {
jvmTarget = "1.8"
}
Expand All @@ -42,4 +63,13 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
implementation("com.github.bumptech.glide:glide:4.16.0")
annotationProcessor("com.github.bumptech.glide:compiler:4.16.0")

implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0")
implementation ("com.google.code.gson:gson:2.8.6")
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
implementation("com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2")
}
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
android:supportsRtl="true"
android:theme="@style/Theme.Android_study_14_2"
tools:targetApi="31">
<activity
android:name=".AddMemoActivity"
android:exported="false" />
<activity
android:name=".MainActivity"
android:exported="true">
Expand Down
52 changes: 52 additions & 0 deletions app/src/main/java/com/alom/androidstudy2/AddMemoActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.alom.androidstudy2

import android.content.Context
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.alom.androidstudy2.databinding.ActivityAddMemoBinding

class AddMemoActivity : AppCompatActivity() {

private lateinit var binding: ActivityAddMemoBinding

private val viewModel: MainViewModel by viewModels {
ViewModelFactory(
RepositoryImpl(
getSharedPreferences("MyPrefs", Context.MODE_PRIVATE),
RetrofitClient.apiService
)
)
}


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityAddMemoBinding.inflate(layoutInflater)
setContentView(binding.root)

binding.btnSave.setOnClickListener {
val title = binding.etTitle.text.toString()
val price = binding.etPrice.text.toString()
val time = binding.etTime.text.toString()


val newMemo = Memo(
title = title,
price = price,
imageUrl = "",
time = time,
id = (0..9999999).random()
)


viewModel.addMemo(newMemo)


finish()
}
}
}
11 changes: 11 additions & 0 deletions app/src/main/java/com/alom/androidstudy2/AddMemoRequest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.alom.androidstudy2

import com.google.gson.annotations.SerializedName



data class AddMemoRequest(
@SerializedName("p_title") val title: String,
@SerializedName("p_price") val price: String,
@SerializedName("p_time") val time: String
)
8 changes: 8 additions & 0 deletions app/src/main/java/com/alom/androidstudy2/AddMemoResponse.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.alom.androidstudy2

import com.google.gson.annotations.SerializedName

data class AddMemoResponse(
@SerializedName("result") val result: Int

)
9 changes: 9 additions & 0 deletions app/src/main/java/com/alom/androidstudy2/GetMemoResponse.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.alom.androidstudy2

import com.google.gson.annotations.SerializedName

data class GetMemoResponse(
@SerializedName("result") val result: Int,
@SerializedName("message") val message: String,
@SerializedName("data") val data: List<Memo>
)
45 changes: 38 additions & 7 deletions app/src/main/java/com/alom/androidstudy2/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,20 +1,51 @@
package com.alom.androidstudy2

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import com.alom.androidstudy2.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding
private lateinit var memoListAdapter: MemoListAdapter


private val viewModel: MainViewModel by viewModels {
ViewModelFactory(
RepositoryImpl(
getSharedPreferences("MyPrefs", Context.MODE_PRIVATE),
RetrofitClient.apiService
)
)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)


memoListAdapter = MemoListAdapter()
binding.recyclerView.adapter = memoListAdapter


lifecycleScope.launchWhenStarted {
viewModel.currentMemo.collect { memoList ->
memoListAdapter.submitList(memoList)
}
}


binding.btnAdd.setOnClickListener {
val intent = Intent(this, AddMemoActivity::class.java)
startActivity(intent)
}
}
}
}
42 changes: 42 additions & 0 deletions app/src/main/java/com/alom/androidstudy2/MainViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.alom.androidstudy2
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class MainViewModel(private val repository: MemoRepository) : ViewModel() {

private var _currentMemo = MutableStateFlow<List<Memo>>(emptyList())
val currentMemo: StateFlow<List<Memo>> get() = _currentMemo.asStateFlow()

init {

loadMemoList()
}

fun loadMemoList() {
viewModelScope.launch {
val memos = withContext(Dispatchers.IO) {
repository.getMemos()
}
_currentMemo.emit(memos)
}
}

fun addMemo(memo: Memo) {
viewModelScope.launch {

withContext(Dispatchers.IO) {
repository.addMemo(memo)
}

val memos = repository.getMemos()

_currentMemo.emit(memos)
}
}
}
13 changes: 13 additions & 0 deletions app/src/main/java/com/alom/androidstudy2/MainviewModelFactory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.alom.androidstudy2

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider

class ViewModelFactory(private val repository: MemoRepository): ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(MainViewModel::class.java)) {
return MainViewModel(repository) as T
}
throw IllegalArgumentException("ViewModel class not found")
}
}
12 changes: 12 additions & 0 deletions app/src/main/java/com/alom/androidstudy2/Memo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.alom.androidstudy2

import com.google.gson.annotations.SerializedName

data class Memo(
@SerializedName("id") val id: Int,
@SerializedName("title") val title: String,
@SerializedName("price") val price: String,
@SerializedName("image_url") val imageUrl: String,
@SerializedName("time") val time: String
)

46 changes: 46 additions & 0 deletions app/src/main/java/com/alom/androidstudy2/MemoListAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.alom.androidstudy2

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.alom.androidstudy2.databinding.ItemMemoBinding
import com.bumptech.glide.Glide


object MemoDiffUtil : DiffUtil.ItemCallback<Memo>() {
override fun areItemsTheSame(oldItem: Memo, newItem: Memo): Boolean {

return oldItem.id == newItem.id
}

override fun areContentsTheSame(oldItem: Memo, newItem: Memo): Boolean {

return oldItem == newItem
}
}


class MemoListAdapter : ListAdapter<Memo, MemoListAdapter.MemoViewHolder>(MemoDiffUtil) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MemoViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ItemMemoBinding.inflate(inflater, parent, false)
return MemoViewHolder(binding)
}

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

inner class MemoViewHolder(private val binding: ItemMemoBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(memo: Memo) {
binding.tvTitle.text = memo.title
binding.tvPrice.text = memo.price
binding.tvTime.text=memo.time
Glide.with(binding.imgItem).load(memo.imageUrl).into(binding.imgItem)
}
}
}
10 changes: 10 additions & 0 deletions app/src/main/java/com/alom/androidstudy2/MemoRepository.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.alom.androidstudy2

interface MemoRepository {
suspend fun getMemos(): List<Memo>
suspend fun addMemo(memo: Memo): AddMemoResponse
suspend fun setMemo(memo: Memo)



}
Loading