ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [TedImagePicker] 1-1. 비동기 방식 이미지 1개 선택 코드 분석
    오픈소스 공부/TedImagePicker 2024. 5. 23. 17:00

     

    링크 : https://github.com/ParkSangGwon/TedImagePicker

     

    TedImagePicker 라이브러리를 다운받고 실행해보면 아래와 같이 나온다. 

     

    스크린샷

     

    MainActivity에 해당되는 부분이다. 

     

    화면을 보면 아래 2가지 정도로 나눠져 있다. 

    • (1) NORMAL/RX (동기/비동기)
    • (2) SINGLE/MULTI (1개/여러개) 

    MainActivity의 첫번째 버튼 코드를 보자면 아래와 같다. 

     

    (현재 MainActivity.kt)

    1. setNormalSingleButton 메서드 

    private fun setNormalSingleButton() {
        binding.btnNormalSingle.setOnClickListener {
            TedImagePicker.with(this)
                .start { uri -> showSingleImage(uri) }
        }
    }

     

    • TedImagePicker의 with 메소드 start 메소드가 연달아 사용됐다.
      • (1) with 메서드를 통해 Builder class를 만들고
      • (2) Builder class 내부의 start 메소드를 사용하고 있다. 
    • start 메소드는 parameter를 통해 showSingleImage 메서드를 고차함수 방식으로 함수를 넘겨주고 있다. (고차함수)

    (현재 MainActivity.kt)

    2. showSingleImage 메서드 

    private fun showSingleImage(uri: Uri) {
        binding.ivImage.visibility = View.VISIBLE
        binding.containerSelectedPhotos.visibility = View.GONE
        Glide.with(this).load(uri).into(binding.ivImage)
    }
    • 선택된 uri를 가져와서 MainActivity 화면에서 보여주는 메서드다. 

    (MainActivity.kt > TedImagePicker로 이동)

    3. TedImagePicker

    class TedImagePicker {
        companion object {
            @JvmStatic
            fun with(context: Context) = Builder(WeakReference(context))
        }
    
        @SuppressLint("ParcelCreator")
        class Builder(private val contextWeakReference: WeakReference<Context>) :
            TedImagePickerBaseBuilder<Builder>() {
            
            ... 생략 ...
            
            fun start(onSelectedListener: OnSelectedListener) {
                this.onSelectedListener = onSelectedListener
                selectType = SelectType.SINGLE
                contextWeakReference.get()?.let {
                    startInternal(it)
                }
            }
    
            fun start(action: (Uri) -> Unit) {
                start(object : OnSelectedListener {
                    override fun onSelected(uri: Uri) {
                        action(uri)
                    }
                })
            }
    
    		... 생략 ...
        }
    }

     

    3-1) with 메서드

    fun with(context: Context) = Builder(WeakReference(context))
    • with 메서드는 Builder class를 인스턴스화 시킨다. 

    3-2) Builder class - 첫번쨰 start 메서드 

    fun start(action: (Uri) -> Unit) {
        Log.d("setNormalSingleButton", "uri")
        start(object : OnSelectedListener {
            override fun onSelected(uri: Uri) {
                action(uri)
            }
        })
    }

     

    • 여기서는 고차함수랑 객체식이라는 개념이 나오나. 
    • start 메서드는 파라미터로 고차함수를 받는다. (parameter : Uri, retrun 값 : Unit)
    • 그리고 또 다른 start 메서드에 객체식을 파라미터로 넘겨준다.
    • OnSelectedListener를 넘겨받은 어딘가에서 onSelected를 통해 Uri 값을 parameter로 넘겨준다면 action(uri)가 실행된다.
    • 여기서 action(uri)는 MainActivity에서 넘겨받은 showSingleImage(uri: Uri)  메서드인다.

    3-3) Builder class - 두번쨰 start 메서드 

    fun start(onSelectedListener: OnSelectedListener) {
        this.onSelectedListener = onSelectedListener
        selectType = SelectType.SINGLE
        contextWeakReference.get()?.let {
            startInternal(it)
        }
    }
    • 또 다른 start 메서드는  onSelectedListener를 건내받고 프로퍼티에 설정된 onSelectedListener에 할당한다.
    • this.onSelectedListener는 Builder가 상속 받은 TedImagePickerBaseBuilder<Builder>에 선언되어있다.
    open class TedImagePickerBaseBuilder<out B : TedImagePickerBaseBuilder<B>>(

     

    • SelectType은 아래와 같이 생겼다. 
    • SINGLE과 MULTI를 나누고 넘겨준다. Parcelable은 serializable 처럼 직렬화를 통해 다른 Activity에 intent를 사용해서 넘겨주는 방식이다. Serializable이 구현은 쉬우나 Parcelable이 더 빠르고 효율적이라고... 
    • selectType도 TedImagePickerBaseBuilder에 구현되어있다.
    @Parcelize
    enum class SelectType : Parcelable {
        SINGLE, MULTI
    }

     

    • 마지막으로 contextWeakReference.get() 하고 난 다음은 startInternal(it)을 실행한다. 

     

    글이 너무 길어지는 것 같아서 2부로 넘어가려한다. 

     

     

    앞으로 시간될때 공부할만한 개념들 :

    • WeakReference(context)
    • contextWeakReference.get()
    • @Parcelize & Parcelable
Designed by Tistory.