[Kotlin] ListViewModel

이상목·2024년 5월 22일
0

Kotlin

목록 보기
9/20

이전 시간에 리스트 뷰를 사용한 예제를 작성했는데, list_item.add("문자열") 과 같이 String 타입의 데이터 하나만을 전달하였습니다.

이번 시간에는 String 형태의 문자열 하나만이 아닌 데이터 객체 형태 자체를 전달하는 시간을 가져보도록 하겠습니다.



1. 리스트 뷰 모델 구성

1-1. 클래스 생성

  • 위 사진과 같이 ListViewModel 클래스를 생성해주었습니다.

1-2. ListViewModel 설정

package com.sangmoki.listview

class ListViewModel {
    var title: String = ""
    var content: String = ""
}
  • Model 객체가 어떠한 정보를 가지고 있는지 Model에 정의합니다.

1-3. ListViewAdapter 설정

package com.sangmoki.listview

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView

// 데이터를 받아주기 위한 Adapter 클래스
// 문자열 데이터를 받기 위해 <String> 타입으로 설정
//class ListViewAdapter(val List : MutableList<String>) : BaseAdapter() {

// ListViewModel 데이터를 받기 위해 <ListViewModel> 타입으로 설정
class ListViewAdapter(val List : MutableList<ListViewModel>) : BaseAdapter() {

    // 전체 아이템의 개수 반환
    override fun getCount(): Int {
        return List.size
    }

    // 아이템 반환 (리스트에서 몇번째에 자리한 아이템인지)
    override fun getItem(position: Int): Any {
        return List[position]
    }

    // 아이템의 ID 반환
    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    // list_view_item에서 설정한 item_list_view 레이아웃을 inflate하여 반환
    // String 타입일 때
//    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
//
//        var convertView = convertView
//
//        // 만약 convertView가 null이라면
//        if (convertView == null) {
//            // item_list_view 레이아웃을 inflate하여 convertView에 저장
//            convertView = LayoutInflater.from(parent?.context).inflate(R.layout.list_view_item, parent, false)
//        }
//
//        // listViewItem 레이아웃에서 TextView를 찾아 data 변수에 저장
//        val data = convertView!!.findViewById<TextView>(R.id.listViewItem)
//
//        // data 변수의 text(android:text)에 List[아이템인덱스]를 넣어준다.
//        data.text = List[position]
//
//
//        // 컨버트뷰를 가져오면 반환해준다.
//        return convertView!!
//    }
    
    // listViewModel 타입일 때 
    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {

        var convertView = convertView

        // 만약 convertView가 null이라면
        if (convertView == null) {
            // item_list_view 레이아웃을 inflate하여 convertView에 저장
            convertView = LayoutInflater.from(parent?.context).inflate(R.layout.list_view_item, parent, false)
        }

        // listViewItem 레이아웃에서 TextView를 찾아 title 변수에 저장
        val title = convertView!!.findViewById<TextView>(R.id.listViewItem)
        // listViewItem 레이아웃에서 TextView2를 찾아 content 변수에 저장
        val content = convertView!!.findViewById<TextView>(R.id.listViewItem2)
        
        // title.text에 List[아이템인덱스].title을 넣어준다.
        title.text = List[position].title
        // content.text에 List[아이템인덱스].content를 넣어준다.
        content.text = List[position].content

        // 컨버트뷰를 가져오면 반환해준다.
        return convertView!!
    }
}
  • 기존에 String 타입으로 받을 때 와 다르게 위에서 정의한 ListViewModel 타입으로 받기 때문에 List[position]은 동일하지만, 객체의 어떤 항목을 사용할 것인지 지정해주어야 합니다.

1-4. list_view_item 레이아웃 TextView 추가

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="80dp">

    <TextView
        android:id="@+id/listViewItem"
        android:text="리스트뷰 아이템"
        android:textSize="30sp"
        android:layout_margin="5dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/listViewItem2"
        android:text="리스트뷰 아이템2"
        android:textSize="20sp"
        android:layout_margin="5dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

 </LinearLayout>
  • String 타입만 사용할 때는 단일 변수였기 때문에 textview 하나로 사용했지만, 지금은 ListViewModel 타입의 객체에서 어떠한 데이터를 바인딩 할것인지 구분하기 위해 textView 하나를 더 생성하였습니다.

1-5. MainActivity 설정

package com.sangmoki.listview

import android.os.Bundle
import android.widget.ListView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)


        /**
         * 단일 String 데이터 예시
         */
//        // String 타입의 가변 배열 변수 생성
//        val list_item = mutableListOf<String>()
//
//        // 가변 배열에 아이템 추가
//        list_item.add("1번째 아이템")
//        list_item.add("2번째 아이템")
//        list_item.add("3번째 아이템")
//
//        // ListView 변수 생성
//        val listview = findViewById<ListView>(R.id.mainListView)
//
//        // ListViewAdapter 클래스의 객체 생성
//        val listAdapter = ListViewAdapter(list_item)
//
//        // ListView activity의 객체의 adapter에 아이템 정보를 담은 listAdapter를 넣어준다.
//        listview.adapter = listAdapter

        /**
         * ListViewModel 데이터 예시
         */
        val list_item = mutableListOf<ListViewModel>()

        // title과 content를 담은 객체 list_item에 추가
        list_item.add (ListViewModel().apply {
            title = "1번째 아이템 제목"
            content = "1번째 아이템 내용"
        })

        list_item.add (ListViewModel().apply {
            title = "2번째 아이템 제목"
            content = "2번째 아이템 내용"
        })

        list_item.add (ListViewModel().apply {
            title = "3번째 아이템 제목"
            content = "3번째 아이템 내용"
        })

        val listview = findViewById<ListView>(R.id.mainListView)
        val listAdapter = ListViewAdapter(list_item)
        listview.adapter = listAdapter
    }
}
  • 기존에 String 타입으로 add 해주었을 때와 다르게 list_item에 add 줄 때 ListViewModel().apply를 통해 각 항목에 데이터를 채워넣어 주었습니다.



2. 실행 화면

  • 기존 String 타입의 데이터 전달 시의 결과와 ListViewModel을 사용한 객체 데이터 전달 시 결과를 비교해보겠습니다.

2-1. ListViewModel 사용 전 String 타입 단일일 경우 실행 결과

2-2. ListViewModel 사용 후 실행 결과

결과적으로 단일 데이터를 넘길 때는 String과 같이 타입을 지정해주는 방법도 나쁘지 않겠지만, 보통 하나의 데이터만을 전달하는 경우는 흔치 않기 때문에, ListViewModel을 활용하는 것을 목표로 해야겠다 !

profile
기록은 기억을 지배한다.

0개의 댓글