1. 기술 면접 연습
접근 제어자의 종류와 각 접근제어자에 대한 설명을 해주세요.
접근 제어자는 클래스, 변수, 메서드 등의 멤버에 대한 접근을 제어하는 키워드입니다. 접근 제어자에는 public, private, protected 주요한 접근 제어자와 각각의 설명입니다.
- public:
- 다른 모든 클래스에서 해당 멤버에 접근할 수 있습니다.
- 공개된(public) 멤버는 어떤 패키지든지 접근할 수 있습니다.
- private:
- 동일한 클래스 내에서만 해당 멤버에 접근할 수 있습니다.
- 클래스 외부에서는 해당 멤버에 접근할 수 없습니다.
- protected:
- 같은 패키지 내의 클래스 및 해당 클래스를 상속한 서브클래스에서 해당 멤버에 접근할 수 있습니다.
- 다른 패키지의 클래스이지만 해당 클래스를 상속한 경우에도 접근이 가능합니다.
- default (package-private):
- 접근 제어자를 지정하지 않은 경우를 말합니다.
- 같은 패키지 내에서만 해당 멤버에 접근할 수 있습니다.
- 다른 패키지에서는 해당 멤버에 접근할 수 없습니다.
2. 최종 프로젝트 5주차
좋아요 한 산 리스트 띄우기
어제는 SharedPreference를 어떤 식으로 처리하는 것이 좋을지 꽤나 고민했다.
String으로 받을지, 아니면 List 형식으로 받을지.
결론적으로, List 형식으로 받기로 결정했다.
그리고 원래는 Object 형식으로 어느 곳에서든 사용하려고 했으나, 오류 폭탄을 맞는 바람에 DetailActivity에서 직접 SharedPreferece를 사용하기로 했다.
우선, 좋아요 버튼을 담당하는 코드 안에 SharedPreference를 저장하는 saveData를 넣었다.
private fun initBookmark(sanlist: SanDetailDTO) {
with(binding) {
val myLikedSan = MyLikedSan(sanlist.mountain, sanlist.thumbnail)
// 초기화
if(sanDetailViewModel.sanLikedList.value?.contains(myLikedSan) == true) {
sanlist.isLiked = true
ivBookmark.setImageResource(R.drawable.ic_bookmark_on)
} else {
sanlist.isLiked = false
ivBookmark.setImageResource(R.drawable.ic_bookmark_off)
}
ivBookmark.setOnClickListener {
Log.d(TAG, "좋아요 클릭")
//ViewModel LiveData로 저장
if (sanlist.isLiked) {
sanDetailViewModel.removeSanLikedList(myLikedSan)
} else {
sanDetailViewModel.addSanLikedList(myLikedSan)
}
sanlist.isLiked = !sanlist.isLiked
ivBookmark.setImageResource(
if (sanlist.isLiked) R.drawable.ic_bookmark_on else R.drawable.ic_bookmark_off
)
saveData(LikedConstants.LIKED_PREFS, LikedConstants.LIKED_PREF_KEY, sanDetailViewModel.sanLikedList.value)
}
}
}
// SharedPreference 저장
private fun <T> saveData(preferKey: String, dataKey: String, data: T) {
val prefs = getSharedPreferences(preferKey, Context.MODE_PRIVATE)
val edit = prefs.edit()
edit.clear()
val json = Gson().toJson(data)
edit.putString(dataKey, json).apply()
Log.d(TAG, "SavedSanList")
}
// SharedPreference 불러오기
private fun loadData() {
val prefs = getSharedPreferences(LikedConstants.LIKED_PREFS, Context.MODE_PRIVATE)
if (prefs.contains(LikedConstants.LIKED_PREF_KEY)) {
val gson = Gson()
val json = prefs.getString(LikedConstants.LIKED_PREF_KEY, "")
try {
val type = object : TypeToken<MutableList<MyLikedSan>>() {}.type
val sanStore: MutableList<MyLikedSan> = gson.fromJson(json, type)
sanDetailViewModel.loadSanLikedList(sanStore)
Log.d(TAG, "저장된 목록 : ${sanStore}")
} catch (e: JsonParseException) {
e.printStackTrace()
}
}
}
그리고 loadData()는 onCreate()에 넣어서 SanDetailActivity에 들어가면 띄우도록 했다.
참고로 SanDetailViewModel에는
private val _sanLikedList : MutableLiveData<MutableList<MyLikedSan>> = MutableLiveData()
private var sanLikedCopyList : MutableList<MyLikedSan> = mutableListOf()
val sanLikedList : LiveData<MutableList<MyLikedSan>> = _sanLikedList
fun addSanLikedList(data: MyLikedSan) {
sanLikedCopyList.add(data)
_sanLikedList.value = sanLikedCopyList
// Log.d(TAG, "addSanLikedList = ${data}")
}
fun removeSanLikedList(data: MyLikedSan) {
sanLikedCopyList.remove(data)
_sanLikedList.value = sanLikedCopyList
// Log.d(TAG, "removeSanLikedList = ${data}")
}
fun loadSanLikedList(data: MutableList<MyLikedSan>) {
sanLikedCopyList = data
_sanLikedList.value = sanLikedCopyList
}
이런 식으로 코드를 짜서 실시간으로 반영되도록 했다.
여기까지 하고 나서 확인해본 결과, SharedPreference는 정상적으로 잘 작동하였다.
이제 이 다음으로는 Fragment에서 이 SharedPreference를 받아와야 하는데 이 Fragment들은 전부 MainActivity에서 받아오기 때문에 받아오는 SharedPreference도 MainActivity에 작성하였다.
private fun loadLikedData() {
val prefs = getSharedPreferences(LikedConstants.LIKED_PREFS, Context.MODE_PRIVATE)
if (prefs?.contains(LikedConstants.LIKED_PREF_KEY) == true) {
val gson = Gson()
val json = prefs.getString(LikedConstants.LIKED_PREF_KEY, "")
try {
val type = object : TypeToken<MutableList<MyLikedSan>>() {}.type
val sanStore: MutableList<MyLikedSan> = gson.fromJson(json, type)
radioListViewModel.loadSanLikedList(sanStore)
Log.d(TAG, "저장된 목록 = $sanStore")
} catch (e: JsonParseException) {
e.printStackTrace()
}
}
}
private val _sanLikedList : MutableLiveData<MutableList<MyLikedSan>> = MutableLiveData()
private var sanLikedCopyList : MutableList<MyLikedSan> = mutableListOf()
val sanLikedList : LiveData<MutableList<MyLikedSan>> = _sanLikedList
fun addSanLikedList(data: MyLikedSan) {
sanLikedCopyList.add(data)
_sanLikedList.value = sanLikedCopyList
// Log.d(TAG, "addSanLikedList = ${data}")
}
fun removeSanLikedList(data: MyLikedSan) {
sanLikedCopyList.remove(data)
_sanLikedList.value = sanLikedCopyList
// Log.d(TAG, "removeSanLikedList = ${data}")
}
fun loadSanLikedList(data: MutableList<MyLikedSan>) {
sanLikedCopyList = data
_sanLikedList.value = sanLikedCopyList
}
마지막으로, MyDetailFragment에서는 이 MainActivity의 ViewModel을 불러왔다.
private val likedSanViewModel by activityViewModels<MainViewModel>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 데이터 받아오기
val myLikedSan = likedSanViewModel.sanLikedList.value
Log.d(TAG, "${myLikedSan}")
if (myLikedSan != null) {
initLikedRecyclerView(myLikedSan)
}
자, 그 결과는…!
드디어 가장 큰 과제 중 하나를 끝마쳤다.
정말 길고도 길었다.
다만, 이것만 툭 하고 끝이 아니고, 몇 가지 디테일한 부분을 더 손봐야 한다.
- 로그인 추가
- 편집으로 상호작용 시키기 (편집에서 삭제하기를 누르면 SanDetail 부분의 좋아요 부분도 덩달아 해제. 그 반대도 마찬가지)
- 저기서 클릭하면 곧바로 SanDetailActivity 부분으로 넘어가기
'[TIL][내일배움캠프]' 카테고리의 다른 글
[내일배움캠프][TIL] 24.03.28 (목) - 최종 프로젝트 6주차 : 최종 발표 준비 (0) | 2024.03.28 |
---|---|
[내일배움캠프][TIL] 24.03.25 (월) - 최종 프로젝트 6주차 (0) | 2024.03.25 |
[내일배움캠프][TIL] 24.03.21 (목) - 최종 프로젝트 5주차 : 추가 구현 (0) | 2024.03.21 |
[내일배움캠프][TIL] 24.03.20 (수) - 최종 프로젝트 5주차 : 추가 구현 (0) | 2024.03.20 |
[내일배움캠프][TIL] 24.03.19 (화) - 최종 프로젝트 5주차 : 추가 구현 (0) | 2024.03.19 |