diff --git a/app/src/main/kotlin/jp/co/yumemi/android/code_check/DetailFragment.kt b/app/src/main/kotlin/jp/co/yumemi/android/code_check/DetailFragment.kt index c8df4dd..3a546ed 100644 --- a/app/src/main/kotlin/jp/co/yumemi/android/code_check/DetailFragment.kt +++ b/app/src/main/kotlin/jp/co/yumemi/android/code_check/DetailFragment.kt @@ -19,8 +19,6 @@ class DetailFragment : Fragment(R.layout.fragment_detail) { private val args: DetailFragmentArgs by navArgs() - private var binding: FragmentDetailBinding? = null - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -28,13 +26,12 @@ class DetailFragment : Fragment(R.layout.fragment_detail) { Log.d("検索した日時", date.toString()) } - binding = FragmentDetailBinding.bind(view) - - val item = args.item + val binding = FragmentDetailBinding.bind(view) - val context = requireContext() + binding.also { + val item = args.item + val context = requireContext() - binding?.let { it.ownerIconView.load(item.ownerIconUrl) it.nameView.text = item.name it.languageView.text = item.language diff --git a/app/src/main/kotlin/jp/co/yumemi/android/code_check/MainFragment.kt b/app/src/main/kotlin/jp/co/yumemi/android/code_check/MainFragment.kt index 4605ec3..3e917dc 100644 --- a/app/src/main/kotlin/jp/co/yumemi/android/code_check/MainFragment.kt +++ b/app/src/main/kotlin/jp/co/yumemi/android/code_check/MainFragment.kt @@ -24,7 +24,7 @@ class MainFragment : Fragment(R.layout.fragment_main) { val binding = FragmentMainBinding.bind(view) - val viewModel = MainViewModel(requireContext()) + val viewModel = MainViewModel(application = requireActivity().application) val layoutManager = LinearLayoutManager(requireContext()) val dividerItemDecoration = DividerItemDecoration(requireContext(), layoutManager.orientation) diff --git a/app/src/main/kotlin/jp/co/yumemi/android/code_check/MainViewModel.kt b/app/src/main/kotlin/jp/co/yumemi/android/code_check/MainViewModel.kt index 4f1e104..e9eb64f 100644 --- a/app/src/main/kotlin/jp/co/yumemi/android/code_check/MainViewModel.kt +++ b/app/src/main/kotlin/jp/co/yumemi/android/code_check/MainViewModel.kt @@ -3,9 +3,11 @@ */ package jp.co.yumemi.android.code_check +import android.app.Application import android.content.Context import android.os.Parcelable -import androidx.lifecycle.ViewModel +import android.util.Log +import androidx.lifecycle.AndroidViewModel import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.engine.android.* @@ -23,58 +25,76 @@ import java.util.* * MainFragment で使用。 */ class MainViewModel( - val context: Context -) : ViewModel() { + application: Application +) : AndroidViewModel(application) { + + companion object { + private val TAG = MainViewModel::class.java.simpleName + } // 検索結果 fun searchResults(inputText: String): List = runBlocking { - val client = HttpClient(Android) - return@runBlocking GlobalScope.async { - val response: HttpResponse = client.get("https://api.github.com/search/repositories") { - header("Accept", "application/vnd.github.v3+json") - parameter("q", inputText) - } + // API 呼び出し前のバリデーション + // query パラメータが空の場合 422 が返る + if (inputText.isBlank()) { + return@runBlocking emptyList() + } - val jsonBody = JSONObject(response.receive()) + val client = HttpClient(Android) + return@runBlocking GlobalScope.async { - val jsonItems = jsonBody.optJSONArray("items") + val result = mutableListOf() - val items = mutableListOf() + try { + val response: HttpResponse = client.get("https://api.github.com/search/repositories") { + header("Accept", "application/vnd.github.v3+json") + parameter("q", inputText) + } + val jsonBody = JSONObject(response.receive()) + val jsonItems = jsonBody.optJSONArray("items") - jsonItems?.let { - for (i in 0 until it.length()) { - val jsonItem = it.optJSONObject(i) + jsonItems?.let { + for (i in 0 until it.length()) { + val jsonItem = it.optJSONObject(i) - val name = jsonItem.optString("full_name") - val ownerIconUrl = jsonItem.optJSONObject("owner")?.optString("avatar_url") ?: "empty_url" - val language = jsonItem.optString("language") - val stargazersCount = jsonItem.optLong("stargazers_count") - val watchersCount = jsonItem.optLong("watchers_count") - val forksCount = jsonItem.optLong("forks_count") - val openIssuesCount = jsonItem.optLong("open_issues_count") + val name = jsonItem.optString("full_name") + val ownerIconUrl = jsonItem.optJSONObject("owner")?.optString("avatar_url") ?: "empty_url" + val language = jsonItem.optString("language") + val stargazersCount = jsonItem.optLong("stargazers_count") + val watchersCount = jsonItem.optLong("watchers_count") + val forksCount = jsonItem.optLong("forks_count") + val openIssuesCount = jsonItem.optLong("open_issues_count") - items.add( - Repository( - name = name, - ownerIconUrl = ownerIconUrl, - language = context.getString(R.string.written_language, language), - stargazersCount = stargazersCount, - watchersCount = watchersCount, - forksCount = forksCount, - openIssuesCount = openIssuesCount + result.add( + Repository( + name = name, + ownerIconUrl = ownerIconUrl, + language = context.getString(R.string.written_language, language), + stargazersCount = stargazersCount, + watchersCount = watchersCount, + forksCount = forksCount, + openIssuesCount = openIssuesCount + ) ) - ) + } } - } + lastSearchDate = Date() - lastSearchDate = Date() + } catch (e: Exception) { + e.localizedMessage?.let { + Log.e(TAG, it) + } + } - return@async items.toList() + return@async result.toList() }.await() } } +val AndroidViewModel.context: Context + get() = getApplication() + @Parcelize data class Repository( val name: String, diff --git a/app/src/main/res/layout/fragment_detail.xml b/app/src/main/res/layout/fragment_detail.xml index 8e1b54f..b1059e0 100644 --- a/app/src/main/res/layout/fragment_detail.xml +++ b/app/src/main/res/layout/fragment_detail.xml @@ -1,108 +1,113 @@ - - + - + - + - + - + - + - + - + - + + + +