[Android 앱 개발 숙련] 과제 - 사과마켓 (4)상세 화면 기능 구현 (feat. Parcelable)

0
post-thumbnail
post-custom-banner

🍥구현 기능

  • 상세 화면 UI 요구사항
    • 가격 1000 단위로 콤마(,) 표시하기
  • 상세 화면 기능 요구사항
    • 항목 정보를 객체로 넘겨받아 정보 표시하기
    • 뒤로가기 아이콘 클릭 시, 메인 화면으로 돌아가기

🍥구현하기

Post.kt

  • 항목 정보(Post) 객체를 intent로 넘기고 받기 위해 Parcelable 인터페이스 구현하기

📌참고자료: Parcelable | Android Developers

  • a typical implementation of Parceable:
 class MyParcelable private constructor(`in`: Parcel) : Parcelable {
     private val mData: Int = `in`.readInt()
     override fun describeContents(): Int {
         return 0
     }
     override fun writeToParcel(out: Parcel, flags: Int) {
         out.writeInt(mData)
     }
     companion object CREATOR: Parcelable.Creator<MyParcelable?> {
         override fun createFromParcel(`in`: Parcel): MyParcelable? {
             return MyParcelable(`in`)
         }
         override fun newArray(size: Int): Array<MyParcelable?> {
             return arrayOfNulls(size)
         }
     }

📌참고자료: Parcelable 구현 생성기 | Android Developers

  • @Parcelize로 클래스에 주석을 달면, Parcelable 구현이 자동으로 생성된다
import kotlinx.parcelize.Parcelize
@Parcelize
class User(val firstName: String, val lastName: String, val age: Int): Parcelable
  • parcelable 구현 생성기(parcelize)를 사용하기 위해
    build.gradle(:app)에 plugin id 추가
plugins {
	//...
    id 'kotlin-parcelize'
}
android{
	//...
}
  • Post 클래스에 @Parcelize 애노테이션 추가, Parcelable 인터페이스 상속
@Parcelize
data class Post(
    val ID:Int,
    //...
) :Parcelable {}

DetailActivity.kt

  • View Binding 사용
  • newIntent(context:Context,post:Post): Intent
    Post 타입 객체를 Extra로 받는 Intent를 생성하는 함수
class DetailActivity : AppCompatActivity() {
    private val TAG = "DetailActivity"
    companion object{
        const val EXTRA_POST = "extra_post"
        fun newIntent(context:Context,post:Post): Intent =
            Intent(context, DetailActivity::class.java).apply {
                putExtra(EXTRA_POST, post)
            }
    }

    private lateinit var binding:ActivityDetailBinding
    private val post by lazy{ intent.getParcelableExtra<Post>(EXTRA_POST) ?: null}

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

        //상세 화면 그리기
        initUI()
        //뒤로가기 버튼
        initBackButton()
    }

    private fun initUI(){
        if(post == null){
            Log.d(TAG, "initUI) post is null")
            return
        }
        binding.apply {
            with(post!!){
                detailIvImage.setImageResource(imageID)
                detailTvWriter.text = writer
                detailTvLoction.text = location
                detailTvTitle.text = title
                detailTvBody.text = body
                detailTvPrice.text = DecimalFormat("#,###").format(price).toString() + "원"
            }
        }
    }
    private fun initBackButton(){
        binding.datailIvBack.setOnClickListener {
            Log.d(TAG, "back button clicked")
            finish()
        }
    }
}

MainActivity.kt

  • RecyclerView 항목 클릭 이벤트 발생 시,
    DetailActivity.newIntent(context, dataSet[position]) 함수를 호출하여
    DetailActivity를 시작하는 Intent를 반환받아 실행 시작
    private fun initRecyclerView(dataSet: MutableList<Post>) { 		
    	binding.mainRecyclerView.apply {
    		//...
            //set adapter
            adapter = MyAdapter(dataSet).apply {
                //set adapter itemClick
                itemClick = object : ItemClick {
                    override fun onClick(view: View, position: Int) {
                        Log.d(
                            TAG,
                            "onClick) position: $position, title: ${dataSet[position].title}"
                        )
                        startActivity(DetailActivity.newIntent(context, dataSet[position]))
                    }
                }
            }
            //...
        }
    }
profile
Be able to be vulnerable, in search of truth
post-custom-banner

0개의 댓글