본문 바로가기

앱 개발/Chapter_Curriculum

[과제] 피드백 (앱 개발 심화)

1) ViewModelProvider는 레거시 코드이므로 by viewModels() 사용하기
https://ddangeun.tistory.com/80

2) _thumbnailUrls는 MutableLiveData(가변 라이브데이터), 언더바가 없는 thumbnailUrlList는 불변 LiveData. (Backing Property) 언더바가 존재하면 읽기/쓰기 가능, 없으면 읽기만 가능.

    private val _thumbnailUrls = MutableLiveData<List<String>>()
    val thumbnailUrls: LiveData<List<String>> = _thumbnailUrls

3) RetrofitService interface에서 아래 "Authorization"에 Default 값을 설정

 @GET("v2/search/image")
    suspend fun getSearchImages(
        @Header("Authorization") Authorization: String = "KakaoAK d7dad5f8832c904973babb0a21d079ab", // Default
        @Query("query") query: String = "검색어",
        @Query("sort") sort: String = "accuracy",
        @Query("page") page: Int = 1,
        @Query("size") size: Int = 80,
    ): Response<SearchResponse>

-> Repository에서 다시 한번 값을 선언하여 인자를 넘길 필요가 없음. 아래 (제거)를 보시면 해당 매개변수는 필요 없음(이미 default값으로 위에 작성하였기 때문).

[Repository.kt] authorization 제거
import com.example.imagesearch.network.RetrofitClient

class Repository {
    suspend fun searchImages(
        query: String,
        sort: String,
        page: Int,
        size: Int,
    ): SearchResponse? {
        return try {
            val response = RetrofitClient.RetrofitInstance.retrofitService.getSearchImages(
                query = "검색어",
                sort = "accuracy",
                page = 1,
                size = 80
            )
            if (response.isSuccessful) {
                response.body()
            } else {
                null
            }
        } catch (e: Exception) {
            throw e
        }
    }
}

    // authorization 제거
    fun searchImages(query: String, sort: String, page: Int, size: Int) {
        viewModelScope.launch {
            val result = repository.searchImages(query, sort, page, size)
        }
    }

4) 검색어에 따라 검색을 하려면 아래와 같이 조금 변경되어야 함
[MainActivity.kt]

    // 검색어 저장
    private fun searchImages() {
        val searchQuery = binding.etSearch.text.toString()
        viewModel.searchImages( // 여기서 viewModel 함수를 호출하여 검색
            query = searchQuery,
            sort = "accuracy",
            page = 1,
            size = 10
        )
        saveLastSearch(searchQuery) // 검색을 했으니 "이미지 검색" 화면을 보여줌
        showFragment(SearchFragment(), R.id.fragment_container_search)
    }

5) Fragment에서 binding 객체를 nullable로 만들고 onDestoyView에서 항상 null 시켜주기 

    private var _binding: FragmentSearchBinding? = null
    private val binding: FragmentSearchBinding
        get()=_binding!!

    // OnCreateView는 View를 생성하는 역할만 함
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View {
        _binding = FragmentSearchBinding.inflate(inflater, container, false)
        return binding.root
    }

    // 항상 View와 관련된 작업은 아래 함수에서 하기 (onViewCreated)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        adapter = SearchAdapter(object : SearchAdapter.OnItemClickListener {
            override fun onItemClick(thumbnailUrl: String, position: Int) {
                // 이미지 클릭시 보관함으로 이동
                navigateToKeepFragment(thumbnailUrl)
            }
        })

        val recyclerView: RecyclerView = binding.recyclerView
        recyclerView.adapter = adapter
        recyclerView.layoutManager = GridLayoutManager(requireContext(), 2)

        viewModel = ViewModelProvider(requireActivity())[MainViewModel::class.java]

        // 썸네일 이미지 리스트 설정
        val thumbnailUrls = arguments?.getStringArrayList(THUMBNAIL_URLS_KEY)
        thumbnailUrls?.let {
            viewModel.setThumbnailUrls(it)
        }

        // _thumbnailUrls를 private으로 만들었기 때문에 thumbnailUrls LiveData를 사용하기
        viewModel.thumbnailUrls.observe(viewLifecycleOwner, Observer {
            adapter.thumbnailUrls
            adapter.notifyDataSetChanged()
        })
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null // null 시켜주기
    }

6) 
@SerializedName -> Gson 방식
@Json -> Moshi 방식

728x90

'앱 개발 > Chapter_Curriculum' 카테고리의 다른 글

내일배움캠프 후기 - 솔직  (0) 2024.07.20
[심화 프로젝트] 회고  (0) 2024.06.01
[과제] 피드백 (앱 개발 숙련)  (0) 2024.05.02
[숙련 프로젝트] 회고  (0) 2024.04.30
Today I Learned and Studied  (0) 2024.04.17