본문 바로가기

Frontend/Kotlin

RecyclerView구현

RecyclerView로 동적목록을 만들 수 있는데 앱을 만들 때 정말 많이 쓰이는 요소이다. 

처음에 구현을 배울 땐 Activity로 구현하는 것으로 익혔으나 어플 내에서는 생각보다 Fragment가 훨씬 많이 쓰이는 것을 깨달았다. 그래서 Fragment안에 RecyclerView를 띄울 수 있도록 할것이다.

*주요클래스

이 동적 목록을 만드는데 필요한 클래스들이다.

-RecyclerView: 데이터에 해당하는 뷰가 포함된 ViewGroup이다. 뷰 자체이므로 레이아웃에 RecyclerView를 추가하면 된다.

-ViewHolder: 목록의 각 개별적 요소들은 뷰 홀더 객체로 정의된다. 뷰 홀더가 생성되었을 때는 뷰 홀더에 연결된 데이터가 없다. 뷰 홀더가 생성된 후 RecyclerView가 뷰 홀더를 뷰의 데이터에 바인딩한다. 

-Adapter: RecyclerView는 뷰를 요청한 다음 어댑터에서 메서드를 호출하여 뷰를 뷰의 데이터에 바인딩한다.

 

<구현방법>

1.

우선 activity_main.xml에 FrameLayout을 넣어준다. 그리고 아이디를 부여한다. 이 부분에 fragment화면을 올릴것이다.

 

2.동적 목록을 넣어줄 fragment.xml과 fragment.kt파일을 동시 생성해준다.

<androidx.recyclerview.widget.RecyclerView
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/rv_profile2"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
    android:orientation="horizontal"
    tools:listitem="@layout/item_recycler_ex2"
    />

다음과 같이 id,방향,그리고 Recyclerview 목록의 요소부분의 디자인을 해줄 xml파일을 listitem부분에 정의해준다. 

item_recycler_ex2.xml파일도 생성해주고 만들고 싶은 목록 아이템을 선언해준다.

 

3.데이터 클래스 만들기

data class ProfileData2(
    val img:Int,
    val title:String,
    val little:String
)

리스트의 각 아이템의 내용이 담길 데이터 클래스를 만든다. 

 

4.어댑터 및 뷰홀더 구현

가장 중요한 부분이라고 생각한다. 

adapter을 정의시 필수 구현해야하는 3가지 메서드들이 있다. 

onCreateViewHolder(): ViewHolder와 그에 연결된 View를 생성하고 초기화하지만 뷰의 콘텐츠를 채우지는 않는다. 각 행의 레이아웃(item_recycler_ex2)를 inflate하여 뷰홀더 생성해준다.

onBindViewHolder():RecyclerView가 ViewHolder를 테이터와 연결할 때 호출한다. 데이터를 사용해 뷰 홀더의 레이아웃을 채운다. 

getItemCount(): RecyclerView는 데이터 세트 크기를 가져올 때 이 메서드를 호출한다. RecyclerView는 이 메서드를 사용해서 항목을 추가로 표시할 수 없는 상황을 확인한다.

 

class ProfileAdapter2(private val profiledatalist: ArrayList<ProfileData2>):
    RecyclerView.Adapter<ProfileAdapter2.MyViewHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_recycler_ex2,
        parent,false)
        return MyViewHolder(itemView)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val currentItem = profiledatalist[position]
        //img title little
        holder.titleimg.setImageResource(currentItem.img)
        holder.title.text = currentItem.title
        holder.little.text = currentItem.little
    }

    override fun getItemCount(): Int {
        return profiledatalist.size
    }

    class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val titleimg:ImageView = itemView.findViewById(R.id.popularphoto)
        val title:TextView = itemView.findViewById(R.id.title)
        val little:TextView = itemView.findViewById(R.id.little)
    }
}

다음과 같이 된다. 그리고 참고로 이미지들은 drawable파일에 모두 넣어주었고 동적 목록에 들어가는 모든 Textview들은 strings.xml파일에 미리 정의해놓았다. 

 

5. 리사이클러뷰에 어댑터 붙이기

Fragment.kt파일에서 fragment위에 띄울 수 있도록 생명주기랑 관련하여 정의해주어야 한다.

private lateinit var adapter2: ProfileAdapter2
private lateinit var recyclerView:RecyclerView
private lateinit var profile2ArrayList:ArrayList<ProfileData2>

lateinit var ImageId:Array<Int>
lateinit var title:Array<String>
lateinit var little:Array<String>

다음과 같이 이 파일에서 쓸 변수들을 연결시켜준다. 

private fun dataInitialize(){
    profile2ArrayList= ArrayList<ProfileData2>()
    ImageId=arrayOf(
        R.drawable.food,
        R.drawable.food2,
        R.drawable.weather,
        R.drawable.my
    )
    title = arrayOf(
        getString(R.string.title1),
        getString(R.string.title2),
        getString(R.string.title4),
        getString(R.string.title3)
    )
    little = arrayOf(
        getString(R.string.title1),
        getString(R.string.title2),
        getString(R.string.title4),
        getString(R.string.title3)
    )
    for(i in ImageId.indices){
        val little = ProfileData2(ImageId[i], title[i],little[i])
        profile2ArrayList.add(little)
    }

}

그리고 ArrayList를 만들고 화면에 보여질 데이터들을 집어넣는다. 

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    dataInitialize()
    //val layoutManager = LinearLayoutManager(context)
    val layoutManager = LinearLayoutManager(context,LinearLayoutManager.HORIZONTAL, false)
    recyclerView = view.findViewById(R.id.rv_profile2)
    recyclerView.layoutManager = layoutManager
    //recyclerView.setHasFixedSize(true)
    adapter2 = ProfileAdapter2(profile2ArrayList)
    recyclerView.adapter = adapter2
}
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // Inflate the layout for this fragment
    //return inflater.inflate(R.layout.fragment_home, container, false)
    return inflater.inflate(R.layout.fragment_home, container,false)

}

onCreateView()로 반환되는 view객체는 onViewCreated()의 파라미터로 전달된다. 

리사이클러뷰에 어댑터도 붙여주고 레이아웃 매니저도 설정해주면된다. 이때 그림의 저 상황은 가로 스크롤을 가능하게 하기 위해서 바꾸었다.

이 후 MainActivity.kt에서 프래그먼트를 띄우는 작업만 해준다면 RecyclerView를 프래그먼트에서 구현할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(구현하면서 궁금했던 context에 대하여)

-어플의 현재 상태를 갖고 있음

-시스템이 관리하고 있는 액티비티, 어플의 정보를 얻기 위해 사용

-안드로이드 시스템 서비스에서 제공하는 API에 접근하기 위해 사용

-Activity, Application 클래스는 context클래스를 상속받은 클래스

두가지로 나뉜다=Application Context/ Activity Context

-Application Context

Activity에서 applicationContext라는 프로퍼티를 통해 얻을 수 있는 싱글톤 인스턴스이다.

라이프사이클과 묶여있어 현재 context가 종료되고 나서도 context가 필요한 작업이나 액티비티 범위를 벗어난 곳에서 context가 필요한 작업에 적합

-Activity Context

해당 Context 는 액티비티 안에서만 사용 가능하다. 특정 Activity 의 라이프 사이클에 종속되어 있다. 이 녀석은 Activity 스코프 내에서 사용될 때 넘겨주거나, Activity  라이프사이클이 같은 객체를 생성할 때 넘겨준다. 즉, Activity 가 소멸되면 해당 Context 도 같이 소멸되는 것이다.

'Frontend > Kotlin' 카테고리의 다른 글

Solution:카카오 소셜 로그인 구현  (0) 2023.01.10
Unit 5  (0) 2023.01.10
Unit 3 solution  (0) 2022.11.20
unit 3 강의 정리  (0) 2022.11.16
2번째 스터디 과제  (0) 2022.11.14