TIL) 230330

Hanseul Lee·2023년 3월 30일
0

TIL

목록 보기
16/23
post-custom-banner

android package와 androidx package

Activity와 Fragment의 기본 틀을 미리 짜두고 싶어서 추상 클래스를 만들었다.

import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding

abstract class BaseActivity<B : ViewBinding>(
    private val inflate: (LayoutInflater) -> B
) : AppCompatActivity() {
    protected lateinit var binding: B
        private set

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

viewBinding 부분을 제외하면 Fragment도 같은 구조를 사용하였기에 생략한다. 그리고 이 베이스 코드를 활용한 Activity 코드는 다음과 같다.

import android.os.Bundle
import hs.project.cof.base.BaseActivity
import hs.project.cof.databinding.ActivityMainBinding

class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate) {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

    }

}

그런데 다음 오류를 발견했다.

Type argument is not within its bounds.
Expected:
ViewBinding
Found:
ActivityMainBinding

분명 ViewBinding을 상속 받도록 코딩했는데 무슨 문제일까? 삽질 끝에 찾아보니 import한 ViewBinding 라이브러리가 어느 package에 속해있는지, 그리고dataBinding의 사용 여부에 따라 해당 오류가 생기는 거였다.

MainActivity 레이아웃 파일의 최상위 레이아웃이 <layout>이었다. dataBinding을 활용하려 했기 때문인데 그래서 이 경우에는 androidx 패키지의 ViewBinding을 사용해야 한다.

import androidx.viewbinding.ViewBinding

왜냐하면 android 패키지는 기존의 안드로이드 프레임워크에서 제공하는 클래스와 API를 포함하고 있고, androidx 패키지는 Jetpack 라이브러리와 함께 제공되기 때문이다.

DialogFragment에서 list 형식으로 출력하기

간단하기 때문에 코드로 살펴보자.

  1. 자식 dialogFragment

    class SettingFragment : DialogFragment() {
    
        private val viewModel: ChatViewModel by activityViewModels()
    
        override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
            return activity?.let {
                val builder = AlertDialog.Builder(it)
                builder.setTitle("버전을 선택해주세요")
                    .setItems(
                        R.array.version_array,
                        DialogInterface.OnClickListener { dialog, which ->
                            val versions = resources.getStringArray(R.array.models_array)
                            val selectedValue = versions[which]
                            viewModel.setModel(selectedValue)
                        })
                builder.create()
            } ?: throw IllegalStateException("Activity cannot be null")
        }
    }
    • setTitle : 타이틀
    • setItems : 출력할 아이템

    resources.getIntArray(R.array.color_values)는 string 배열 리소스를 가져와서 versions 배열에 저장한다. 그런 다음 versions[which]는 선택한 인덱스 which에 해당하는 string 값을 가져온다. 이 값을 selectedValue 변수에 할당하고, viewModel에 세팅한다.

  2. dialogFragment를 호출하는 부모 Fragment

    class ChatFragment : BaseFragment<FragmentChatBinding>(FragmentChatBinding::inflate) {
    		
    		..
    
    		private fun modelSettingListener() {
            binding.mainActionbarSettingIb.setOnClickListener {
                val dialogFragment = SettingFragment()
                dialogFragment.show(childFragmentManager, "settings_dialog")
            }
        }
    }
  3. 데이터를 가지고 있는 ViewModel

    class ChatViewModel : ViewModel() {
    		..
    		private var _model = String()
    
    		fun setModel(model: String) {
            _model = model
        }
    
    		..
    
    		fun getMessage(msg: String) {
            viewModelScope.launch {
                _apiStatus.value = MessageApiStatus.LOADING
                try {
                    val chat = ChatRequest(model = _model, messages = listOf(RequestMessage(content = msg, role = "user")))
                    addMessage(Message(ChattingApi.retrofitService.getMessage(BuildConfig.API_KEY, chat).choices[0].message.content, SEND_BY_BOT))
                    _apiStatus.value = MessageApiStatus.DONE
                } catch (e: Exception) {
                    addMessage(Message("다음 사유로 응답에 실패했습니다.\n$e", SEND_BY_BOT))
                    _apiStatus.value = MessageApiStatus.ERROR
                }
            }
        }
    }
  4. xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string-array name="version_array">
            <item>채팅</item>
            <item>번역</item>
            <item>질문</item>
        </string-array>
    
        <string-array name="models_array">
            <item>gpt-3.5-turbo</item>
            <item>gpt-3.5-turbo</item>
            <item>gpt-3.5-turbo</item>
        </string-array>
    </resources>

post-custom-banner

0개의 댓글