DBILITY

독거 가능성 100% 노후에 라면값이라도 하게 센스를 발휘합시다!😅
Please click on the ad so that I can pay for ramen in my old age!
点击一下广告,让老后吃个泡面钱吧!
老後にラーメン代だけでもするように広告を一回クリックしてください。

안드로이드 RecyclerView 기초 사용법 ( viewMoldel update 적용 ) 본문

android

안드로이드 RecyclerView 기초 사용법 ( viewMoldel update 적용 )

DBILITY 2024. 3. 11. 11:25
반응형

MutableStateFlow에 MutableList형을 넣어(?)  자료를 추가,삭제,갱신해 봤다.

이게 맞는 건지는 모르겠다. 되는대로 하였음

액티비티

 

아이템용 뷰

ViewModel.kt

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class TodoViewModel : ViewModel() {

    companion object {
        private const val TAG = "LOG - TodoViewModel"
    }

    private val _items = MutableStateFlow<MutableList<Todo>>(mutableListOf())
    val items: StateFlow<MutableList<Todo>> = _items.asStateFlow()
    private val dataList = mutableListOf<Todo>()

    init {
        for (idx in 1..100) {
            dataList.add(Todo(idx, "do something $idx", System.currentTimeMillis()))
        }
        viewModelScope.launch {
            _items.value = dataList
        }
    }

    fun addTodo(text: String) {
        viewModelScope.launch {
            _items.update {
                it.toMutableList().apply {
                    val maxId = fold(
                        Todo(0, "", System.currentTimeMillis()
                        )
                    ) { acc, todo -> if (acc.id.compareTo(todo.id) == 1) acc else todo }.id + 1
                    val todo = Todo(maxId, text, System.currentTimeMillis())
                    add(todo)
                }
            }
        }
    }

    fun updateTodo(id: Int, text: String) {
        viewModelScope.launch {
            _items.update {
                it.map { value->
                    if(value.id==id) {
                        value.copy(todo=text, datetime = System.currentTimeMillis())
                    } else {
                        value
                    }
                }.toMutableList()
            }
        }

    }

    fun deleteTodo(id: Int) {
        viewModelScope.launch {
            _items.update {
                it.toMutableList().apply {
                    find { value -> value.id == id }?.let { todo ->
                        remove(todo)
                    }
                }
            }
        }
    }

}

MainActivity.kt

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
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.Lifecycle
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSmoothScroller
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.SmoothScroller
import com.example.myrecyclerviewbyviewmodel.databinding.ActivityMainBinding
import com.example.myrecyclerviewbyviewmodel.databinding.ItemViewBinding
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat

class MainActivity : AppCompatActivity() {

    companion object {
        private const val TAG = "LOG - MainActivity"
    }

    private val binding by lazy {
        ActivityMainBinding.inflate(layoutInflater)
    }

    private var isExists: Boolean = false
    private var selectedId: Int = 0

    private val viewModel:TodoViewModel by viewModels()
    //private lateinit var viewModel: TodoViewModel
    private val dateFormatter = SimpleDateFormat("yyyy-MM-dd")
    private val todoListAdapter = TodoListAdapter(
        fun(data: Todo) {
            binding.activityMainPlainTextTodo.setText(data.todo)
            isExists = true
            selectedId = data.id
        },
        fun(data: Todo) {
            viewModel.deleteTodo(data.id)
        }
    )
    private val smoothScroller: SmoothScroller by lazy {
        object : LinearSmoothScroller(binding.root.context) {
            override fun getVerticalSnapPreference(): Int {
                return SNAP_TO_START
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(binding.root)
        ViewCompat.setOnApplyWindowInsetsListener(binding.main) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }


        with(binding) {

            //viewModel = ViewModelProvider(this@MainActivity)[TodoViewModel::class.java]

            lifecycleScope.launch {
                //fragment에서는 viewLifecycleOwner.repeatOnLifecycle
                repeatOnLifecycle(Lifecycle.State.STARTED) {
                    viewModel.items.collect {
                        Log.d(TAG, it.toString())
                        todoListAdapter.submitList(it)

                        activityMainPlainTextTodo.text.clear()
                        isExists = false
                        selectedId = 0
                    }
                }
            }

            activityMainRecyclerView.apply {
                layoutManager = LinearLayoutManager(root.context)
                smoothScroller.targetPosition = viewModel.items.value.size - 1
                layoutManager!!.startSmoothScroll(smoothScroller)
                itemAnimator = null
                adapter = todoListAdapter
            }
            activityMainButtonSave.setOnClickListener {
                if (activityMainPlainTextTodo.text.isNullOrEmpty()) {
                    Toast.makeText(root.context, "input something!!", Toast.LENGTH_SHORT).show()
                    return@setOnClickListener
                }
                Log.d("isExists", isExists.toString())
                if (!isExists) {
                    viewModel.addTodo(activityMainPlainTextTodo.text.toString())
                    smoothScroller.targetPosition = viewModel.items.value.size - 1
                    activityMainRecyclerView.layoutManager!!.startSmoothScroll(smoothScroller)
                } else {
                    viewModel.updateTodo(selectedId, activityMainPlainTextTodo.text.toString())
                }

                val manager = root.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                manager.hideSoftInputFromWindow(root.windowToken, 0)
            }

        }

    }

    inner class TodoListAdapter(
        private val onClickListener: (Todo) -> Unit,
        private val buttonOnClickListener: (Todo) -> Unit
    ) :
        ListAdapter<Todo, TodoViewHolder>(TodoDiffItemCallback()) {
        private lateinit var itemViewBinding: ItemViewBinding
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoViewHolder {
            itemViewBinding =
                ItemViewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
            return TodoViewHolder(itemViewBinding, onClickListener, buttonOnClickListener)
        }

        override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
            holder.bind(getItem(position))
        }
    }

    inner class TodoViewHolder(
        private val itemViewBinding: ItemViewBinding,
        private val onClickListener: (Todo) -> Unit,
        private val buttonOnClickListener: (Todo) -> Unit
    ) :
        RecyclerView.ViewHolder(itemViewBinding.root) {
        fun bind(todo: Todo) {
            with(itemViewBinding) {
                itemViewId.text = todo.id.toString()
                itemViewTodo.text = todo.todo
                itemViewDatetime.text = dateFormatter.format(todo.datetime)
                root.setOnClickListener {
                    onClickListener(todo)
                }
                itemViewButtonDelete.setOnClickListener {
                    buttonOnClickListener(todo)
                }
            }
        }
    }

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

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

실행화면

반응형
Comments