본문 바로가기

내일배움캠프

본 캠프 50일 차 - 개인 과제

내 보관함으로 서버에서 요청한 데이터 리스트를 클릭을 통해 옮기기

오늘 한 일

  • api 요청을 통해 가져온 데이터 중 클릭을 통해 메인 액티비티의 아이템 리스트로 보내고 이를 내 보관함에 연결해서 내 보관함에 리스트 띄우기
  • 코드 리펙토링을 통해 코드를 좀 더 간결하고 가시성이 좋게 바꾸기

어제 어댑터에 연결해서 내 보관함에 리스트를 띄우기 위해 메인에 함수를 만들고 로그를 통해 확인 해보았지만 타지 않았던 onclick 되었을 때의 로그에서 이제 리스트를 띄우기 위하여 좀 바꿔보았다.

if (items != myList) {
    (mContext as MainActivity).like(MyItems(
    items[position].thumbnail_url,items[position].datetime,items[position].display_sitename))
    }else{
    (mContext as MainActivity).unLike(MyItems(
    items[position].thumbnail_url,items[position].datetime,items[position].display_sitename))
    }

if() 안에 들어가서 비교할 내용을 찾다보니 이렇게 하니 오류가 뜨지 않아서 이거구나 했지만 결과는...

어...? 사진이 안뜬다...시간만 제대로 온다... + 심지어 처음에 클릭한 것만 들어가고 이후에 추가적으로 누르는건 업데이트가 되지 않는다... 대체 왜 사진이 안뜨는지 로그까지 따봤지만 도저히 몰라서 튜터님을 찾아갔다.

 

 

data class MyItems(
    var location : String,
    var time : String,
    var imageUrl : String,
)

 

해결 : MyItems를 보면 location -> display_sitename , time -> datetime, imageUrl -> thubnail_url 인데 이 순서대로 넣은게 아니라 location과 imageUrl의 위치가 바뀌어서 일어난 일이라고 짚어주셨다.

아...답은 허무하게 해결되었다.

 

문제

  • 리스트에서 아무것도 선택하지 않고 보관함으로 넘어가면 앱이 죽어버림
  • 추가는 되지만 삭제가 되지않음
  • 코드가 난잡해서 어디에 어떤걸 구현했는지 찾기 어려움

 

해결1

우선 앱이 죽는 현상은 리스트가 0인 상태를 넣어주면 그냥 빈 화면만 출력 되는데 그래서 일단 지연초기화로 

private lateinit var myList : List<MyItems>

이렇게 위에 프로퍼티를 선언해 두고 똑같이 어댑터도 지연초기화로 

private var myItemsAdapter = MyItemsAdapter(myList)

이렇게 두개를 선언 해 줬는데...이번엔 오류로 켜지지 않는다. 어댑터가 초기화 되지 않는다고 로그캣에 떠서 어떻게 해야하나 싶었는데 이를 똑같이 지연초기화로 선언하고 밑에 뷰에서 어댑터에 myList를 넣어보았다.

그런데 이번에는 mainactivity쪽 초기화가 안되었다고 한다...어질어질...

private lateinit var mContext: Context
private lateinit var myList : List<MyItems>
private lateinit var myItemsAdapter : MyItemsAdapter

메인초기화를 위한 mContext를 선언하고 리스트와 어댑터도 선언해 줬다. 이제 이를 

override fun onAttach(context: Context) {
    super.onAttach(context)
    mContext = context
    myList = (mContext as MainActivity).myItemList()
    myItemsAdapter = MyItemsAdapter(myList)
}

onAttach에서 초기화 되게 이렇게 만들어 줬다. 이러니 이제 아무것도 선택하지 않고도 내 보관함으로 넘어올 수 있게 되었다.

 

해결2

삭제가 안되던 문제는 아까 맨 위에서 추가하기 위해 넣었던 if(items != myList) 가 문제였다. items는 api를 통해 가져오는 documents타입, myList는 내가 보관함에 더 추가할 즐겨찾기도 넣기 위해 만든 MyItems 타입이라 결국 서로 다르기에 무조건 추가만 되는 상황이었다. 따라서 두 비교구문을 통일 시켜줘야 했다.

이를 위해 items[position].display_sitename, items[position].datetime, items[position].thumbnail_url을 각각 loc, time, url로 변수 선언을 해주었다. 그리고 이제 이를 MyItems타입을 바꾸기 위해 item이란 변수를 선언하고 그 안에 MyItems()를 넣고 이 괄호 안에 이 세 개를 MyItems의 순서에 맞게 넣어줬다.

val loc = items[position].display_sitename
val time = items[position].datetime
val url = items[position].thumbnail_url
val item = MyItems(loc, time, url)

이제 items가 item으로 MyItems 타입이 되었다. 이제 이게 myList에 있는지 확인하기 위해 contains를 사용하여 다시 만들어주면

if (!myList.contains(item)) {
    mContext.like(item)
} else {
    mContext.unLike(item)
}

그리고 코드가 길어져서 (mContext as MainActivity)를 위에 

private lateinit var mContext: MainActivity

로 선언해주고 대신 onAttach에서

override fun onAttach(context: Context) {
    super.onAttach(context)
    mContext = context as MainActivity
}

좀 더 길어졌다. 결국 onAttach와 if문의 mContext가 바뀐 것이다. 

이렇게 해주니 보관함에 있던걸 리스트에서 누르니 삭제가 되는 로그를 볼 수 있었다. 하지만 이걸 해주려면 내 보관함 프래그먼트에서 onResume 안에 어댑터에 메인액티비티의 리스트를 연결해 주고 다음에 notifyDataSetChanged를 통해 리스트를 바꿔주는 코드를 넣으니 해결 되었다.

override fun onResume() {
    super.onResume()
    myItemsAdapter.myItemList = (mContext as MainActivity).myItemList()
    myItemsAdapter.notifyDataSetChanged()

    emptyView()
}

이제 내 보관함 리스트의 삭제와 추가가 실시간으로 이루어진다.

 

해결 3

override fun 부분 안에서 여러가지 기능들을 코드로 쭉 나열하면 내가 어디에 무엇을 만들었는지 찾지 못하는 등의 가독성의 문제가 있다. 이를 팀원과 같이 내 코드를 보면서도 내가 이걸 어디에 만들었는지 한참 찾고 있는 걸 보니 문제가 있다고 생각이 들긴 했는데 이를 기능별로 함수로 만들어서 밖으로 빼내서 하는게 좋다고 가독성이 좋게 코드를 만드는 법을 알려주어서 이제 안에는 함수를 집어 넣고 밖에다가 기능을 구현하는 방식을 어렵더라도 해봐야겠다. 일단 이건 직접 계속 쳐보는 방법밖에 없을 거 같다.

 

일단 리스트는 옮겨다닐 수 있으니 이제 좋아요 표시가 나오게끔 내일 만들어보아야겠다.