๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿค2024 ์•ˆ๋“œ๋กœ์ด๋“œ/Filmo ์˜ํ™” ํ”„๋กœ์ ํŠธ

๐Ÿฃ๋ฉ”์ธ ํ™”๋ฉด API ์—ฐ๋™ ์ขŒ์ถฉ์šฐ๋Œ๊ธฐ ๊ธฐ๋ก

by hyeonha 2024. 4. 8.

๋ชฉ์ฐจ

    ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—

    ์˜ค๋Š˜์€ ๋ฉ”์ธ ํ™”๋ฉด์—์„œ ์“ฐ์ด๋Š” api์™€ ์—ฐ๋™ํ•˜๋Š” ๊ณผ์ •์„ ๊ธฐ๋กํ•˜์˜€๋‹ค. 

    1๏ธโƒฃ๋ฉ”์ธ ํ™”๋ฉด : ๊ฐ์ƒ๋ฌธ ์กฐํšŒ ๊ธฐ๋Šฅ ๊ตฌํ˜„

    ๋ฉ”์ธ ํ™”๋ฉด์—์„œ๋Š” ์ „์ฒด ๊ฐ์ƒ๋ฌธ์„ ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ๋กœ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. ํ˜„์žฌ๋Š” ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ์ƒ๋ฌธ์„ ๋ณด์—ฌ์ฃผ๋Š”๋ฐ, ์ด์ œ API์™€ ์—ฐ๋™ํ•˜์—ฌ ์‹ค์ œ ๊ฐ์ƒ๋ฌธ ๋‚ด์šฉ๊ณผ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ์ž‘์—…์„ ํ•˜๋ ค ํ•œ๋‹ค. ๋จผ์ € API์™€ ์—ฐ๋™๋ถ€ํ„ฐ ํ•ด์ฃผ์—ˆ๋‹ค.

     

    ๐Ÿค๋ฐฐ์šด ์ 

    1๏ธโƒฃRepository๋„ interface๋กœ ์ •์˜ ํ›„ ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค.

    2๏ธโƒฃ์ธํ„ฐํŽ˜์ด์Šค์™€ hilt ์‚ฌ์šฉ๋ฒ•

     

     

    ์ด๋ ‡๊ฒŒ Repository๋ฅผ interface๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค.

    interface ReportRepository {
        suspend fun searchReport(): Result<String>
    }

     

    ๊ทธ๋ฆฌ๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด searchReport ํ•จ์ˆ˜๋ฅผ ์žฌ์ •์˜ํ•ด์ฃผ์—ˆ๋‹ค.

    class ReportRepositoryImpl
        @Inject
        constructor(
            private val reportDataSource: ReportDataSource,
        ) : ReportRepository {
            override suspend fun searchReport(): Result<String> {
                return reportDataSource.searchReport()
            }
        }

     

     

    ์ด๋ ‡๊ฒŒ ์ธํ„ฐํŽ˜์ด์Šค์ธ ReportRepository ๊ฐ์ฒด๋ฅผ ๋ทฐ ๋ชจ๋ธ์—์„œ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ReportModule๋ฅผ ์ •์˜ํ•ด์ฃผ์—ˆ๋‹ค.

    ์ด ๋•Œ Hilt ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ • ์œ ํ˜•์˜ ์ธ์Šคํ„ด์Šค ์ œ๊ณต ๋ฐฉ๋ฒ•์„ Hilt์— ์•Œ๋ ค์ค€๋‹ค. 

     

    ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฝ์ž…ํ•ด์ฃผ๊ธฐ

    - Hilt module์€ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ์ง€์ •ํ•ด์ค€๋‹ค. 

    - @Binds๋กœ ์ฃผ์„์ด ์ง€์ •๋œ ์ถ”์ƒ ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•ด์„œ Hilt์—๊ฒŒ ๊ฒฐํ•ฉ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•œ๋‹ค.  

    - ํ•จ์ˆ˜ ๋ฐ˜ํ™˜ ์œ ํ˜•์€ ํ•จ์ˆ˜๊ฐ€ ์–ด๋–ค ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š”์ง€๋ฅผ Hilt์—๊ฒŒ ์•Œ๋ ค์ค€๋‹ค.
        -> ์šฐ๋ฆฌ๋Š” ReportRepository ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค๊ณ  ์•Œ๋ ค์ฃผ์—ˆ๋‹ค.

    - ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์ œ๊ณตํ•  ๊ตฌํ˜„์„ Hilt์—๊ฒŒ ์•Œ๋ ค์ค€๋‹ค. 
        -> ์šฐ๋ฆฌ๋Š” ReportRepositoryImpl ์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋„˜๊ฒจ์ฃผ์—ˆ๋‹ค.

    @InstallIn(SingletonComponent::class)
    @Module
    abstract class ReportModule {
        @Binds
        @Singleton
        abstract fun bindReportRepository(impl: ReportRepositoryImpl): ReportRepository
    
        @Binds
        @Singleton
        abstract fun bindReportDatasource(impl: ReportDataSourceImpl): ReportDataSource
    }

     

    ์ด๋ ‡๊ฒŒ ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ Hilt์— ๊ฒฐํ•ฉ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•œ ํ›„์— ๋Š”  ์ด์ œ ์ƒ์„ฑ์ž ์‚ฝ์ž…์„ ์‚ฌ์šฉํ•˜์—ฌ ReportRepository ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค! 

     

    @HiltViewModel
    class ReportViewModel
        @Inject
        constructor(private val reportRepository: ReportRepository) :
        ViewModel() {
            suspend fun getReportList() {
                viewModelScope.launch {
                    reportRepository.searchReport()
                }
            }
        }

     

     

    2๏ธโƒฃ์‘๋‹ต๊ฐ’์„ DTO์™€ ์—ฐ๊ฒฐํ•˜์—ฌ ์ „์ฒด ๊ฐ์ƒ๋ฌธ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ์™€ ์—ฐ๊ฒฐํ•ด์ฃผ๊ธฐ 

    ๋ชจ๋ฅด๋Š” ์ 

    ๐Ÿ”นDTO๋ฅผ ์ž‘์„ฑํ•ด์ฃผ๋ ค๊ณ  ํ•˜๋‹ˆ response์˜ body์—์„œ [ ] ๋Œ€๊ด„ํ˜ธ์™€ { } ์ค‘๊ด„ํ˜ธ์˜ ์ฐจ์ด์˜ ์˜๋ฏธ๋ฅผ ๋ชจ๋ฅด๊ณ  ์žˆ์—ˆ๋‹ค.

     

        { } ๋Š” ๊ฐ์ฒด๋ฅผ ํ‘œํ˜„ํ•œ๋‹ค. ๊ฐ์ฒด๋Š” ํ‚ค์™€ ๊ฐ’์˜ ์Œ์œผ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

        [ ] ๋Š” ๋ฐฐ์—ด์„ ํ‘œํ˜„ํ•œ๋‹ค. ๋ฐฐ์—ด์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ’์„ ์ˆœ์„œ๋Œ€๋กœ ๋‚˜์—ดํ•œ ๊ฒƒ์ด๋‹ค. 

        ํฐ ๊ตฌ์กฐ๋ฅผ repoList๋ฅผ ์‚ดํŽด๋ณด๋ฉด 

        "repoList" : [ {๊ฐ์ฒด1}, {๊ฐ์ฒด2}, {๊ฐ์ฒด3}, ``` ] ๋กœ ๊ตฌ์„ฑ๋˜์–ด์žˆ๋‹ค. 

         key : value ์Œ!

        reportList๋ผ๋Š” ํ‚ค์— ๋Œ€์‘ํ•˜๋Š” ๊ฐ’์ด  ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ์ฒด๋“ค์ด ์ˆœ์„œ๋Œ€๋กœ ๋‚˜์—ด๋œ ๋ฐฐ์—ด๋กœ ์ดํ•ดํ•˜๋ฉด ๋œ๋‹ค. 

        ์ด๋ฅผ data class๋กœ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ•˜๋ฉด , ์ด๋ ‡๊ฒŒ ReportList ๊ฐ์ฒด๋ฅผ ์ •์˜ํ•ด์ฃผ๊ณ , ์ด๋Ÿฌํ•œ ๊ฐ์ฒด๊ฐ€ ๋‚˜์—ด๋œ ๋ฐฐ์—ด์„ ๋‹ด์€ ๋ณ€์ˆ˜์ธ         reportList๋ฅผ ์ •์˜ํ•ด์ฃผ์—ˆ๋‹ค. 

    data class ReportInfo(
        val reportList: List<ReportList>,
        ````
    )
    
    data class ReportList(
        ```
    )

     

    ๐Ÿ”นkotlin์—์„œ List์™€ ArrayList์™€ mutableList์˜ ์ฐจ์ด์— ๋Œ€ํ•ด ์ œ๋Œ€๋กœ ์•Œ์ง€ ๋ชปํ–ˆ๋‹ค.

        kotlin์—์„œ๋Š” ๋ณ€์ˆ˜๋“ค์„ Mutable ์—ฌ๋ถ€๋กœ ๋‚˜๋ˆ„๊ณ  ์žˆ๋‹ค.

        List์™€ MutableList์˜ ์ฐจ์ด๋„ Read-Only์ธ์ง€ ์•„๋‹Œ์ง€์˜ ์ฐจ์ด์ด๋‹ค. 

        List๋Š” ์˜ค์ง ์ฝ๊ธฐ ์ ‘๊ทผ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.

        MutableList๋Š” ์ฝ๊ธฐ/์“ฐ๊ธฐ ์ ‘๊ทผ์ด ์ง€์›๋œ๋‹ค. 

        Array์™€ List์˜ ์ฐจ์ด๋Š” ๋ฌด์—‡์ผ๊นŒ?

     

        ArrayList๋Š” ๋ฌด์—‡์ผ๊นŒ?

     

     

    ๋ฐœ์ƒํ•œ ์—๋Ÿฌ : 

    java.lang.IllegalArgumentException: Unable to create converter for class cohttp://m.teamfilmo.filmo.ui.model.ReportInfo

     

    ํ•ด๊ฒฐ : ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ retrofit ๊ตฌ์„ฑ ์‹œ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

    .addConverterFactory(GsonConverterFactory.create())
    

     

    ๊ฒฐ๊ณผ : ์ด๋ ‡๊ฒŒ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค! 

     

     

    ๐Ÿค”Json ๊ด€๋ จ converter๋„ ์žˆ๋˜๋ฐ Gson๊ณผ Json Converter์˜ ์ฐจ์ด๊ฐ€ ๋ฌด์—‡์ผ๊นŒ?

     

    ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์‘๋‹ต๊ฐ’์œผ๋กœ ์˜จ ReportList๋“ค์„ ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ์ž‘์—…์„ ํ•ด๋ณด์ž. ์ฒ˜์Œ์ด๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ป๊ฒŒํ•ด์•ผํ• ์ง€ ๋จผ์ € ์ •๋ฆฌ๋ฅผ ํ•ด๋ณด์•˜๋‹ค.


    ์ˆœ์„œ๋ฅผ ์ •๋ฆฌํ•ด๋ณด๋ฉด

    1๏ธโƒฃAPI๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์— ์ €์žฅ๋œ ๊ฐ์ƒ๋ฌธ ๋‚ด์šฉ ์ „์ฒด๋ฅผ ๋ถˆ๋Ÿฌ์˜จ๋‹ค

    ๋ทฐ ๋ชจ๋ธ์—์„œ ReportInfo ๋‚ด์— ์žˆ๋Š” ReportList๋ฅผ ์–ด๋Œ‘ํ„ฐ์™€ ์—ฐ๊ฒฐํ•ด์ค€๋‹ค. 

     

    2๏ธโƒฃ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ์˜ ์–ด๋Œ‘ํ„ฐ์— ํ•ด๋‹น ๊ฐ์ƒ๋ฌธ ๋ฆฌ์ŠคํŠธ๋ฅผ ์—ฐ๊ฒฐํ•ด์ค˜์„œ ๋ทฐ์™€ ๋ฐ”์ธ๋”ฉํ•ด์ค€๋‹ค. 

     

    ์–ด๋–ป๊ฒŒ ์–ด๋Œ‘ํ„ฐ์™€ ReportList๋ฅผ ์—ฐ๊ฒฐํ•ด์ค„๊นŒ ???

     

    ๐Ÿค1์ฐจ ๊ตฌํ˜„ ๊ธฐ๋ก

    ๊ตฌํ˜„ ํ๋ฆ„  

    ๐Ÿ”น ๋ทฐ๋ชจ๋ธ์—์„œ ๊ฐ์ƒ๋ฌธ ์กฐํšŒ ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๊ธฐ

    ๋ทฐ๋ชจ๋ธ์—์„œ  ReportRepository.searchReport ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœ

    ์–ป์€ ์‘๋‹ต๊ฐ’์˜ ReportInfo ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ReportList๋ฅผ ์ถ”์ถœํ•œ ๋ฐ์ดํ„ฐ๋ฅผ MutableLiveData์ธ ReportList์˜ value๊ฐ’์œผ๋กœ  ๋„ฃ์–ด์ค€๋‹ค. 

     

    ๐Ÿ”น์ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ์™€ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

     

    Adapter์—์„œ List<ReportList> ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์„ reportList ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๊ณ  

     

     

    1๏ธโƒฃReportViewModel

    @HiltViewModel
    class ReportViewModel
        @Inject
        constructor(private val reportRepository: ReportRepository) :
        ViewModel() {
            val reportList = MutableLiveData<List<ReportList>?>()
    
            init {
                requestReportList()
            }
    
            fun requestReportList() {
                viewModelScope.launch {
                    val result = reportRepository.searchReport()
                    if (result.isSuccess) {
                        val response = result.getOrNull()
                        val reports = response?.reportList?.toList()
                        Log.d("๊ฐ์ƒ๋ฌธ", reportList.toString())
                        reportList.value = reports
                    } else {
                        result.getOrThrow()
                    }
                }
            }
        }

     

    ๐Ÿ”นMutableLiveData 

    ๐Ÿ”นinit { ``` } ์˜ ์‚ฌ์šฉ

    ๐Ÿ”นviewModelScope.launch { ``` }

     

    2๏ธโƒฃ ReportFragment

    private val reportViewModel by viewModels<ReportViewModel>()
    
    runBlocking {
                reportViewModel.requestReportList()
            }
    
            val movieReviewAdapter = ReviewAdapter()
    
            reportViewModel.reportList.observe(viewLifecycleOwner) { reports ->
                if (reports != null) {
                    movieReviewAdapter.setReportList(reports)
                }
            }

    ๐Ÿ”นrunBlocking ๊ณผ runCatching์˜ ์ฐจ์ด 

    ๐Ÿ”นobserve ๋ž€? 

    ๐Ÿ”นviewLifeCycleOwner ๋ž€?

     

    ๋ทฐ ๋ชจ๋ธ์˜ reportList๋ฅผ ๊ด€์ฐฐํ•˜๊ณ , ์ด ReportList๊ฐ€ null์ด ์•„๋‹ˆ๋ผ๋ฉด ์–ด๋Œ‘ํ„ฐ์˜ setReportList๋ฅผ ํ˜ธ์ถœํ•ด์ค€๋‹ค. ์ด ๋•Œ List<ReportList> ๋ฅผ ๊ฐ™์ด ์ „๋‹ฌํ•ด์ค€๋‹ค

     

     

     3๏ธโƒฃ ReportAdapter

    ๊ทธ๋Ÿผ ์–ด๋Œ‘ํ„ฐ์—์„œ๋Š” ๊ทธ List<ReportList>๋ฅผ ๋ฐ›์•„์„œ ์–ด๋Œ‘ํ„ฐ ํด๋ž˜์Šค์˜ ์†์„ฑ์ธ reportList ๊ฐ’์— ๋„ฃ์–ด์ฃผ๊ณ , notifyDataSetChanged ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด์ค€๋‹ค.

     

    class ReviewAdapter : RecyclerView.Adapter<ReviewAdapter.ReviewViewHolder>() {
        private var reportList: List<ReportList> = listOf()
    
        fun setReportList(reportList: List<ReportList>) {
            this.reportList = reportList
            notifyDataSetChanged()
        }

     

    ๐Ÿ”นnotifyDataSetChanged( )๋ž€?

     

    notifyDataSetChanged ๋ž€ ?

     

    ๊ทผ๋ฐ ์ง€๊ธˆ์€ searchReport ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์„œ๋ฒ„์— ์ €์žฅ๋œ ์ „์ฒด ๊ฐ์ƒ๋ฌธ์„ ๋ถˆ๋Ÿฌ์˜ค๋Š”๋ฐ notifyDataSetChanged๋ฅผ ํ˜ธ์ถœํ•ด์ค˜์•ผํ• ๊นŒ? ํ•˜๋Š” ์˜๋ฌธ์ด ๋“ค์—ˆ๋‹ค.

    ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋ฐ”๋กœ ๋ฐ”์ธ๋”ฉํ•ด์ฃผ๋Š”๋ฐ ์™œ ์—…๋ฐ์ดํŠธ๊ฐ€ ํ•„์š”ํ• ๊นŒ ์กฐ๊ธˆ ๋” ์ฐพ์•„๋ด์•ผ๊ฒ ๋‹ค.

     

    ๊ทธ๋ž˜์„œ notifyDataSetChanged์— ์ฃผ์„์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ  ๋‹ค์‹œ ์‹คํ–‰ํ–ˆ๋”๋‹ˆ...!!!  ์•„๋ฌด๊ฒƒ๋„ ๋ณด์ด์ง€ ์•Š์•˜๋‹ค. 
    ์šฐ์„  notifyDataSetChanged ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฏํ•˜๋Š” ๊ฒƒ์€ ํ•„์š”ํ–ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ๋กœ ์ธํ•ด ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ์—์„œ ๋ณด์—ฌ์ค„ ์•„์ดํ…œ๊ณผ ๊ฐœ์ˆ˜๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค! 

    ๐Ÿค๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ ๋ฐฉ๋ฒ•์—๋Š” ๋ฌด์—‡์ด ์žˆ์„๊นŒ?

     

    ๋ฉ”์ธํ™”๋ฉด์— ์กด์žฌํ•˜๋Š” ํ”„๋ž˜๊ทธ๋จผํŠธ, ์–ด๋Œ‘ํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

    ํ˜„์žฌ ๋ฉ”์ธ ํ™”๋ฉด์—์„œ ์ „์ฒด ๊ฐ์ƒ๋ฌธ์ด ๋ณด์ด๋Š” ์ „์ฒด ํƒญ๊ณผ ํŒ”๋กœ์šฐํ•˜๋Š” ๊ฐ์ƒ๋ฌธ๋งŒ ๋ณด์ด๋Š” ํŒ”๋กœ์ž‰ ํƒญ์ด ์žˆ๋‹ค.

     

    ํ˜„์žฌ ์ƒํ™ฉ์„ ์ •๋ฆฌํ•ด๋ณด๋ฉด,

    ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ๋กœ ์•„์ดํ…œ๋“ค์„ ๋ณด์—ฌ์ค„ ๋•Œ ๊ณตํ†ต์ ์œผ๋กœ searchReport api๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์•„์ดํ…œ์„ ๋ณด์—ฌ์ค€๋‹ค. 

    ์ฐจ์ด๋Š” searchReport์— ๋“ค์–ด๊ฐ€๋Š” ์ธ์ž์˜ ์ฐจ์ด์ด๋‹ค.

    [์ „์ฒด]์˜ ๊ฒฝ์šฐ  ์•„๋ฌด ์ธ์ž์—†์ด searchReport api๋ฅผ ํ˜ธ์ถœํ•ด์ค„ ๊ฒฝ์šฐ 

    [ํŒ”๋กœ์ž‰]์˜ ๊ฒฝ์šฐ ํŒ”๋กœ์šฐํ•˜๋Š” ์‚ฌ๋žŒ์˜ ๊ฒŒ์‹œ๊ธ€๋งŒ ๋ณด๊ธฐ ์œ„ํ•ด์„œ์„œ๋Š” ์ „์ฒด ์ค‘์—์„œ ํŒ”๋กœ์šฐํ•˜๋Š” ์‚ฌ๋žŒ์˜ ๊ฐ์ƒ๋ฌธ ๊ฒŒ์‹œ๊ธ€๋งŒ ๋ณด์ด๋„๋ก ํ•„ํ„ฐ๋ง์ด ํ•„์š”ํ•˜๋‹ค. 

    ์šฐ์„ ์€ ์–ด๋–ป๊ฒŒ ํ•„ํ„ฐ๋ง ํ•  ๊ฒƒ์ธ์ง€๋ณด๋‹ค๋Š” ์ „์ฒด ๊ตฌ์กฐ๋ฅผ ์งœ๋ณด์ž!

     

    ๋‚˜๋Š” Adapter๋ฅผ ๋ณ„๋„๋ก 2๊ฐœ ๊ตฌํ˜„ํ•ด์ค˜์•ผํ• ๊นŒ? ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ๋ทฐ ํ™€๋” 2๊ฐœ๊ฐ€ ํ•˜๋‚˜์˜ ์–ด๋Œ‘ํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๋ฉด ์•ˆ๋ ๊นŒ? 

     

     

    ๐Ÿ”ฅ์–ด๋Œ‘ํ„ฐ์—์„œ ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด๋„ ๋˜๋Š”๊ฐ€?

    ๋ฐœ์ƒ ์—๋Ÿฌ 

    handleAppError, pkgName : com.teamfilmo.filmo, userId : 0, errorType : 9, repeat : true component : com.teamfilmo.filmo.ui.report.ReportViewModel.<init> []errorStack: Caused by: java.lang.NoSuchMethodException: com.teamfilmo.filmo.ui.report.ReportViewModel.<init> []
                                                                                                        	at java.lang.Class.getConstructor0(Class.java:2363)
                                                                                                        	at java.lang.Class.getDeclaredConstructor(Class.java:2201)
                                                                                                        	at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:199)
                                                                                                        	... 57 morejava.lang.RuntimeException: Cannot create an instance of class com.teamfilmo.filmo.ui.report.ReportViewModel
                                                                                                        	at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.

     

    ์›์ธ : ์ด ์—๋Ÿฌ๋Š” FollowingFragment์—์„œ ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ @AndroidEntryPoint ์–ด๋…ธํ…Œ์ด์…˜์„ ์ ์–ด์ฃผ์ง€์•Š์•„์„œ ๋ฐœ์ƒํ•œ ์—๋Ÿฌ์˜€๋‹ค! 

    ํ•ด๊ฒฐ : ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€ 

     

    3  3056-3056  SDHMS:BarT...r:AppError com.sec.android.sdhms                I  update AppError : uid=10607, pkg=com.teamfilmo.filmo, errorType=crash
    2024-04-11 01:09:26.161  3056-3056  SDHMS:BarT...r:AppError com.sec.android.sdhms                I  analyze app error : uid=10607, pkg=com.teamfilmo.filmo, appErrorCount=2

     

    ๋‘ ํ”„๋ž˜๊ทธ๋จผํŠธ์—์„œ ๋™์ผํ•˜๊ฒŒ ๋ทฐ๋ชจ๋ธ์˜ requestReportList ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๋„๋ก ์ฝ”๋“œ ์ž‘์„ฑ ์‹œ 
    ํŒ”๋กœ์ž‰ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•œ ํ›„ 1์ดˆ ์ดํ›„์— ์•ฑ์ด ๋น„์ •์ƒ ์ข…๋ฃŒ๋˜์—ˆ๋‹ค. 

     

    ์‹œํ—˜์ด ๋๋‚˜๊ณ  ๋‹ค์‹œ ๋Œ์•„์™”๋‹ค!! 20240426!!

    ์ €๋ฒˆ์— ์ด์–ด ์•„์ง ํ•ด๊ฒฐ๋˜์ง€ ์•Š์€ ์•„๋ž˜์˜ ์—๋Ÿฌ๋ฅผ ํŒŒ์•…ํ•ด๋ณด์ž!

    2024-04-26 23:01:58.562  3132-3132  SDHMS:BarT...r:AppError com.sec.android.sdhms                I  update AppError : uid=10607, pkg=com.teamfilmo.filmo, errorType=crash
    2024-04-26 23:01:58.565  3132-3132  SDHMS:BarT...r:AppError com.sec.android.sdhms                I  analyze app error : uid=10607, pkg=com.teamfilmo.filmo, appErrorCount=5

     

     Calling a method in the system process without a qualified user: android.app.ContextImpl.sendBroadcast:1242 com.android.server.am.AppErrors.crashApplicationInner:724 com.android.server.am.AppErrors.crashApplication:584 com.android.server.am.ActivityManagerService.handleApplicationCrashInner:9748 com.android.server.am.ActivityManagerService.handleApplicationCrash:9627

     

    ํ™•์ธ์„ ์œ„ํ•ด์„œ ์šฐ์„  Following Fragment์™€ Adapter ์ฝ”๋“œ๋ฅผ ์ฃผ์„ ์ฒ˜๋ฆฌ ํ›„ ์‹คํ–‰ํ•ด์ฃผ์—ˆ๋‹ค. 

     

    ์ด๋ฅผ ํ†ตํ•ด  ๋ณ€์ˆ˜ ์ดˆ๊ธฐํ™” ๊ณผ์ •์— ๋ฌธ์ œ๊ฐ€ ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

     

    ์•„๋ž˜์™€ ๊ฐ™์ด reviewAdapter ๋ณ€์ˆ˜์— ๋Œ€ํ•ด ์„ ์–ธํ•ด์ฃผ๊ณ , ์ดˆ๊ธฐํ™” ์ž‘์—…์€ ์ดํ›„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ์—ˆ๋‹ค.

        private lateinit var reviewAdapter: ReviewAdapter

     

    ๊ทธ๋Ÿฌ๋‚˜ ์•„๋ž˜์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์ค€ ํ›„์ธ๋ฐ ์ •์˜ํ•ด์ค€ ์ฝ”๋“œ์— ์ ์šฉ์ด ๋˜์ง€ ์•Š์•˜๋‹ค. 

    reviewAdapter = ReviewAdapter()

     

    ์‹คํ–‰ ์ •์ƒํ™”

    ๐Ÿซฑ๋ฒ„ํŠผ ํด๋ฆญ์œผ๋กœ ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ๋ณ€๊ฒฝํ•ด์ฃผ๋Š”๋ฐ ๋ทฐํŽ˜์ด์ €2๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ• ๊นŒ?ํ•˜๋Š” ์˜๋ฌธ์ด ๋“ค์—ˆ๋‹ค. 

     

    ๊ณต์‹๋ฌธ์„œ์—์„œ ๋ทฐํŽ˜์ด์ €2๋ฅผ "์Šค์™€์ดํ”„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ทฐ ๋˜๋Š” ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ์ œ๊ณต" ์ด๋ผ๊ณ  ์„ค๋ช…ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.

    ๋”ฐ๋ผ์„œ ๋ทฐํŽ˜์ด์ €2๊ฐ€ ์•„๋‹Œ ํด๋ฆญ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๋กœ ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ๋ณ€๊ฒฝํ•ด์ฃผ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด์ฃผ์—ˆ๋‹ค.

     

    ์—ฌ๊ธฐ์„œ ๋ฐฐ์šด ๋‚ด์šฉ์€ ํ”„๋ž˜๊ทธ๋จผํŠธ๋ฅผ ๋ณด์—ฌ์ค„ ๋•Œ supportFragmentManager์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค! 

       override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            binding = ActivityMainPageBinding.inflate(layoutInflater)
            setContentView(binding.root)
            setFrag(0)
    
            binding.allReportButton.setOnClickListener {
                setFrag(0)
            }
            binding.FollowingReportButton.setOnClickListener {
                setFrag(1)
            }
        }
    
        private fun setFrag(fragNum: Int) {
            val fragment = supportFragmentManager.beginTransaction()
            when (fragNum) {
                0 -> fragment.replace(R.id.fragmentArea, ReviewFragment()).commit()
                else -> fragment.replace(R.id.fragmentArea, FollowingReviewFragment()).commit()
            }
        }

     

    ๐Ÿ‘์ข‹์•„์š” ๋ฒ„ํŠผ ์—ฐ๋™ํ•˜๊ธฐ

    ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ์— ์žˆ๋Š” โค๏ธ ์ข‹์•„์š” ๋ฒ„ํŠผ์„ ํด๋ฆญ ํ•  ๋•Œ๋งˆ๋‹ค ์ข‹์•„์š”๊ฐ€ ๋“ฑ๋ก๋˜๋„๋ก ํ•ด๋ณด์ž! 

     

    ์šฐ์„  ํด๋ฆญ์ด ์ •์ƒ์ ์œผ๋กœ ๋˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์œ„ํ•ด ๋กœ๊ทธ๋กœ ํ™•์ธํ•ด์ค€ ๊ฒฐ๊ณผ OK์˜€๋‹ค!

     

    ์ง€๊ธˆ ๊ตฌ์กฐ๋ฅผ ์ •๋ฆฌํ•ด๋ณด๋ฉด

    ๋ฉ”์ธ ํŽ˜์ด์ง€์—์„œ 2๊ฐœ์˜ ํ”„๋ž˜๊ทธ๋จผํŠธ ํ™”๋ฉด์„ ์ œ๊ณตํ•˜๊ณ  

    ๊ฐ ํ”„๋ž˜๊ทธ๋จผํŠธ ํ™”๋ฉด์—์„œ๋Š” ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š”๋ฐ ์ด ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ์—๋Š” ๋ฆฌ๋ทฐ ๋ฐ์ดํ„ฐ + ์ข‹์•„์š” + ๋Œ“๊ธ€ + ๋ถ๋งˆํฌ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•จ๊ป˜ํ•˜๊ณ  ์žˆ๋‹ค.

     

    ์ข‹์•„์š” ๋“ฑ๋ก ๊ธฐ๋Šฅ์„ ์—ฐ๋™ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋Š”๋ฐ.. ํ—˜๋‚œํ•œ ์—ฌ์ •์ด ํŽผ์ณ์กŒ๋‹ค.

    ์šฐ์„  ์ข‹์•„์š”๋ฅผ ์„œ๋ฒ„์— ๋“ฑ๋กํ•˜๋ ค๋ฉด ํ˜„์žฌ์˜ ์•„์ดํ…œ์˜ reportId๋ฅผ ๊ฐ™์ด ๋„˜๊ฒจ์„œ ํ˜ธ์ถœํ•ด์ค˜์•ผํ•œ๋‹ค.

     

    ์–ด๋””์„œ ํ˜ธ์ถœ์„ ํ•ด์ค˜์•ผํ• ๊นŒ? 

     

    728x90