ꡬκΈμμ μ 곡νλ κ΅μ‘μλ£λ₯Ό μ 리νκΈ° μν ν¬μ€νΈμ λλ€.
μ±μ λ―Όκ°ν μ¬μ©μ λ°μ΄ν°μ νΉμ μμ€ν κΈ°λ₯μ λν μ κ·Ό κΆνμ μμ²ν΄μΌ ν©λλ€.
AndroidManifest.xml
μμ <uses-permission>
νκ·Έλ‘ μ μΈν©λλ€.AndroidManifest.xml
μ USE_BIOMETRIC
κΆνμ μΆκ°ν©λλ€. USE_BIOMETRIC
κΆνμ ν΅ν΄ μ체 μΈμ λ°©μμ μ¬μ©ν μ μμ΅λλ€. μΌλ° λ³΄νΈ λ 벨μ΄λ©° μ± μ€μΉ μ λΆμ¬λ©λλ€.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sampleapp">
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<application>
<activity
android:name=".MainActivity" ... >
...
</activity>
</application>
</manifest>
μ±μ΄ λ€νΈμν¬ μμ
μ μνν΄μΌ νλ κ²½μ° AndroidManifest.xml
μ μλ κΆνμ μ μΈν΄μΌ ν©λλ€. μΌλ° λ 벨μ΄λ―λ‘ μΆκ° μμ
μ΄ νμνμ§ μμ΅λλ€.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
μ± Gradle νμΌμ μ’ μμ±μ μΆκ°ν©λλ€. JSONμμ κ°μ²΄λ‘μ λ³νμ μν΄ Moshiλ₯Ό μ¬μ©ν©λλ€.
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-moshi:2.9.0"
implementation "com.squareup.moshi:moshi:$moshi_version"
implementation "com.squareup.moshi:moshi-kotlin:$moshi_version"
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
@Path : λμ μΌλ‘ URLμ λν΄ μλνλ ν¨μλ₯Ό λ§λ€ μ μμ΅λλ€.
@Query : 쿼리 맀κ°λ³μλ₯Ό μΆκ°ν μ μμ΅λλ€.
@Body : HTTP μμ² Bodyμ μ λ¬ν μ μμ΅λλ€.
interface SimpleService {
@GET("posts")
suspend fun listPosts(): List<Post>
@GET("posts/{userId}")
suspend fun listByUser(@Path("userId") userId:String): List<Post>
@GET("posts/search") // becomes post/search?filter=query
suspend fun search(@Query("filter") search: String): List<Post>
@POST("posts/new")
suspend fun create(@Body post : Post): Post
}
Retrofit.Builder() λ₯Ό μ¬μ©νμ¬ Retrofit κ°μ²΄λ₯Ό μμ±ν©λλ€.
μλΉμ€ μΈν°νμ΄μ€λ₯Ό μ¬μ©νμ¬ μλΉμ€μ ꡬ체μ μΈ κ΅¬νμ λ§λλλ€.
val retrofit = Retrofit.Builder()
.baseUrl("https://example.com")
.addConverterFactory(...)
.build()
val service = retrofit.create(SimpleService::class.java)
Response λ₯Ό ν΄λμ€ κ°μ²΄λ‘ λ³ννλ λ° λμμ΄ λ©λλ€.
맀νμ μννλ μ΄λν°λ₯Ό μλμΌλ‘ μμ±νκΈ° μν΄ generateAdapter = trueλ‘ μ€μ νμ΅λλ€.
@JsonClass(generateAdapter = true)
data class Post (
val title: String,
val description: String,
val url: String,
val updated: String,
val thumbnail: String,
val closedCaptions: String?)
λ€μμ JSON μλ΅μ λλ€. Moshiλ μ΄ μλ΅μ κ°μ²΄λ‘ λ³νν©λλ€.
{
"title":"Android Jetpack: EmojiCompat",
"description":"Android Jetpack: EmojiCompat",
"url":"https://www.youtube.com/watch?v=sYGKUtM2ga8",
"updated":"2018-06-07T17:09:43+00:00",
"thumbnail":"https://i4.ytimg.com/vi/sYGKUtM2ga8/hqdefault.jpg"
}
μλΉμ€λ₯Ό μΈμ€ν΄μ€ννλ λμμ MoshiConverterFactory μ€μ νλ λ°©λ²μ λλ€.
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
val retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(BASE_URL)
.build()
object API {
val retrofitService : SimpleService by lazy {
retrofit.create(SimpleService::class.java)
}
}
ViewModelμμ μ½λ£¨ν΄μ μμν©λλ€.
viewModelScope.launch {
Log.d("posts", API.retrofitService.searchPosts("query"))
}
implementation "com.github.bumptech.glide:glide:$glide_version"
Glideλ₯Ό lifecycle ownerμ μ°κ²°νκ³ μ§μ λ URLμ μ΄λ―Έμ§λ₯Ό ImageViewμ λ‘λν©λλ€.
Glide.with(fragment)
.load(url)
.into(imageView);
@BindingAdapter("imageUrl")
fun bindImage(imgView: ImageView, imgUrl: String?) {
imgUrl?.let {
val imgUri = imgUrl.toUri().buildUpon().scheme("https").build()
Glide.with(imgView)
.load(imgUri)
.apply(RequestOptions()
.placeholder(R.drawable.loading_animation)
.error(R.drawable.ic_broken_image))
.into(imgView)
}
}