728x90
검색어 기록을 담당하는 layout의 height을 wrap_content로 변경해 photoGridRecyclerView 위에서 보이도록 변경
//activity_collection.xml
<LinearLayout
android:id="@+id/linear_search_history"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical"
android:visibility="invisible"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
tools:visibility="visible">
onOptionsItemSelected()
를 이용해 선택된 menu의 item 별로 작업하도록 코드를 수정
//CollectionActivity.kt
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
// 매뉴를 생성
Log.d(Constants.TAG, "CollectionActivity - onCreateOptionMenu() called")
val inflater = menuInflater
inflater.inflate(R.menu.top_app_bar_menu, menu)
// 매뉴인플레이터로 매뉴xml과 매개변수로 들어오는 매뉴와 연결
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
// System으로 부터 SearchManager를 가져옴
this.mSearchView =
menu?.findItem(R.id.search_menu_item)?.actionView as androidx.appcompat.widget.SearchView
this.mSearchView.apply {
this.queryHint = "검색어를 입력해주세요"
this.setOnQueryTextListener(this@CollectionActivity)
// 위에서 정의한 구현할 setOnQueryTextListener와 현재 setOnQueryTextListener를 연결
this.setOnQueryTextFocusChangeListener { _, hasFocus ->
//hasFocus : SearchView의 활성화, 비활성화 상태를 가져오는 리스너
when (hasFocus) {
// Linear_Search_History 활성화 유무를 변경
true -> {
Log.d(Constants.TAG, "CollectionActivity - 서치뷰 활성화")
binding.linearSearchHistory.visibility = View.VISIBLE
}
false -> {
Log.d(Constants.TAG, "CollectionActivity - 서치뷰 비활성화")
binding.linearSearchHistory.visibility = View.INVISIBLE
}
}
}
// SearchView의 EditText를 가져온다.
mSearchViewEditText = this.findViewById(androidx.appcompat.R.id.search_src_text)
}
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.more_menu_item -> {
}
R.id.search_menu_item -> {
//textChanges() : editText의 내용이 있는지 없는지 확인
//RxBinding을 통해서 text가 변경되면 Observable을 만듬
val editTextChangeObservable = mSearchViewEditText.textChanges()
// debounce 오퍼레이터 추가
//Observable에서 발행된 item들의 원천인 Observable과 최종의 Subscriber 사이에서 조작
val searchEditTextSubscription: Disposable =
//글자가 입력되고 0.8초 후 onNext() 이벤트로 데이터 보내기
//debounce() : 연속적인 이벤트를 처리하는 흐름 제어 함수
editTextChangeObservable.debounce(800, TimeUnit.MILLISECONDS)
// subscribeOn() : 작업 스레드를 설정
// Schedulers.io() : 동기 I/O를 별도로 처리해 비동기 효율을 얻는 스케줄러
.subscribeOn(Schedulers.io())
//구독하여 이벤트에 대한 응답을 받게된다.
.subscribeBy(
onNext = {
Log.d(Constants.TAG, "onNext : $it")
if (it.isNotEmpty()) {
searchPhotoApiCall(it.toString())
}
},
onComplete = {
//실행되면 흐름이 끊김
Log.d(Constants.TAG, "onComplete")
},
onError = {
//실행되면 흐름이 끊김
Log.d(Constants.TAG, "onError")
}
)
compositeDisposable.add(searchEditTextSubscription)
//Observable 객체에서 발행된 후 반환된 객체의 관리를 위해 compositeDisposable에 추가
// SearchView의 EditText에 길이 제한, 컬러를 수정
mSearchViewEditText.apply {
this.filters = arrayOf(InputFilter.LengthFilter(15))
this.setTextColor(Color.WHITE)
this.setHintTextColor(Color.WHITE)
}
}
}
return super.onOptionsItemSelected(item)
}
enqueue()를
enqueue()
를 이용한 CallBack 메소드로 구현되어 있는 코드를 coroutine
로 변경
//RetrofitManager.kt
private val mjob = Job()
private val mScope = CoroutineScope(Dispatchers.Main + mjob)
// http call 생성
// 레트로핏 인터페이스 가져오기
private val iretrofitService: IRetrofit_Service? =
RetrofitClient.getClient(API.BASE_URL)?.create(IRetrofit_Service::class.java)
//사진검색 api 호출
fun searchPhotos(searchTerm: String?, completion: (RESPONSE_STATE, ArrayList<Photo>?) -> Unit) {
val term = searchTerm.let { it } ?: ""
mScope.launch {
var parsedPhotoDataArray = ArrayList<Photo>()
val job = launch(Dispatchers.IO) {
val call =
iretrofitService?.serachPhotos(searchTerm = term).let { it } ?: return@launch
val body = call.asJsonObject
val results = body.getAsJsonArray("results")
val total = body.get("total").asInt
Log.d(Constants.TAG, "${HomeViewModel::class.java.simpleName} " +
"/ message : ${total}")
if (total != 0) {
// JsonArray result[] 내부의 JsonObject를 하나씩 받아 반복 수행
results.forEach { resultItem ->
val resultItemObject = resultItem.asJsonObject // get object
val user =
resultItemObject.get("user").asJsonObject // object -> user
val username = user.get("username").asString // user -> username
val likeCount =
resultItemObject.get("likes").asInt // object -> likes
val thumbnail =
resultItemObject.get("urls").asJsonObject.get("thumb").asString // urls -> thumb
val createdAt =
resultItemObject.get("created_at").asString // object -> create_at
Log.d(Constants.TAG, "${HomeViewModel::class.java.simpleName} " +
"/ message : ${user}")
Log.d(Constants.TAG, "${HomeViewModel::class.java.simpleName} " +
"/ message : ${username}")
Log.d(Constants.TAG, "${HomeViewModel::class.java.simpleName} " +
"/ message : ${likeCount}")
Log.d(Constants.TAG, "${HomeViewModel::class.java.simpleName} " +
"/ message : ${thumbnail}")
Log.d(Constants.TAG, "${HomeViewModel::class.java.simpleName} " +
"/ message : ${createdAt}")
val parser = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
// 실제 Date 형태
val formatter = SimpleDateFormat("yyyy년\nMM월 dd일")
// 변경하려는 Date 형태
val outputDateString = formatter.format(parser.parse(createdAt))
// Date를 원하는 형태로 치환
//Log.d(Constants.TAG, "RetrofitManager - onResponse() called / outputDateString : ${outputDateString}")
val photoItem = Photo(
author = username,
likesCount = likeCount,
thumbnail = thumbnail,
createdAt = outputDateString
)
parsedPhotoDataArray.add(photoItem)
//ArrayList에 Photo 타입의 데이터를 추가가
}
}
}
job.join()
if(job.isCompleted){
completion(RESPONSE_STATE.OK, parsedPhotoDataArray)
}
}
}
Localization : en이 기본, 한국어 추가
// strings.xml (b+ko)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">사진검색 API</string>
<!-- activity_home.xml / HomeAcitivty.kt -->
<string name="Photo_search">사진검색</string>
<string name="User_search">사용자검색</string>
<string name="Enter_search_word">검색어를 입력하시오.</string>
<string name="String_length_limit">검색어 제한 : 15자</string>
<string name="No_search_results">검색 결과가 없습니다. </string>
<!-- customlayout_button -->
<string name="search">SEARCH</string>
<!-- activity_collection -->
<string name="page_title">사진검색</string>
<string name="more">더보기</string>
<string name="content_description_search">사진을 검색합니다.</string>
<string name="content_description_more">더보기 메뉴입니다.</string>
<string name="search_history_save">검색어 저장</string>
<string name="search_history_clear">전체 삭제</string>
</resources>
//strings.xml
<resources>
<string name="app_name">Photo search API</string>
<!-- activity_home.xml / HomeAcitivty.kt -->
<string name="Photo_search">Photo search</string>
<string name="User_search">User Search</string>
<string name="Enter_search_word">Please enter a search term.</string>
<string name="String_length_limit">Search term limit: 15 characters</string>
<string name="No_search_results">No results were found for your search.</string>
<!-- customlayout_button -->
<string name="search">SEARCH</string>
<!-- activity_collection -->
<string name="page_title">Photo search</string>
<string name="more">View more</string>
<string name="content_description_search">Search for photos.</string>
<string name="content_description_more">This is the more menu.</string>
<string name="search_history_save">Save search term</string>
<string name="search_history_clear">Delete all</string>
</resources>
'Project' 카테고리의 다른 글
09_mvvm : Network communication using retrofit - Search User Test (0) | 2021.02.23 |
---|---|
Goni95_App (0) | 2021.02.02 |