libs.versions.toml retrofit & viewmodel
🤔やってみたいこと
- 🛜Jetpack ComposeでAPI通信をしたい
- 📡HTTP GETだけでもやってみたく💦
- Retrofitの使い方
APIからデータを取得する簡単なデモアプリの開発をして知識を学ぶ内容になっております。
こちらのAPIからデータを取得する
- 開発環境
- M2 Mac
- Android Studio
- compileSdk = 35
- targetSdk = 35
こちらが完成品です参考にしてみてください。
🚀やってみたこと
前回、libs.versions.tomlの記事を書きました。以前だとライブラリの追加は、build.gradle.kts
にこのように追加していました。
implementation 'com.squareup.retrofit2:retrofit:(insert latest version)'
今だとdouble quoteと()で囲んでいますけどね。こんな感じで。
implementation ("com.squareup.retrofit2:retrofit:(insert latest version)")
今回使用したライブラリは、API通信に必要なRetrofitと状態管理をするviewmodelです。こちらを追加しておいてください。
build.gradle.ktsの設定
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
}
android {
namespace = "com.example.jetpackhttpdemo"
compileSdk = 35
defaultConfig {
applicationId = "com.example.jetpackhttpdemo"
minSdk = 24
targetSdk = 35
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
// この下にライブラリを追加して補完機能で設定を変更する。
// Retrofit for API requests
implementation (libs.retrofit)
implementation (libs.converter.gson)
// ViewModel and LiveData for MVVM architecture
implementation (libs.androidx.lifecycle.viewmodel.compose)
implementation (libs.androidx.lifecycle.livedata)
}
Permissionの許可をする。
data/
ディレクトリを作成してdata classを作成する。APIのJSONのデータ構造に合わせて作成。
package com.example.jetpackhttpdemo.data
data class Post(
val id: Int,
val userId: Int,
val title: String,
val body: String
)
api/
ディレクトリにinterfaceを作成します。postsというエンドポイントへアクセスする設定をします。
package com.example.jetpackhttpdemo.api
import com.example.jetpackhttpdemo.data.Post
import retrofit2.http.GET
interface JsonPlaceholderApi {
@GET("posts")
suspend fun getPosts(): List<Post>
}
repository/
ディレクトリを作成する。こちらでbaseUrlを設定します。先ほどのinterface
のgetPosts()
メソッドを呼び出してHTTP GETするメソッドを呼び出しています。
package com.example.jetpackhttpdemo.repository
import com.example.jetpackhttpdemo.api.JsonPlaceholderApi
import com.example.jetpackhttpdemo.data.Post
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class PostRepository {
private val api: JsonPlaceholderApi by lazy {
Retrofit.Builder()
.baseUrl("https://jsonplaceholder.typicode.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(JsonPlaceholderApi::class.java)
}
suspend fun getPosts(): List<Post> = api.getPosts()
}
viewmodel/
ディレクトリを作成してView側にAPIから取得したデーターを渡す状態管理をするためのViewModelを作成します。
package com.example.jetpackhttpdemo.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.jetpackhttpdemo.data.Post
import com.example.jetpackhttpdemo.repository.PostRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class PostViewModel : ViewModel() {
private val repository = PostRepository()
private val _posts = MutableStateFlow<List<Post>>(emptyList())
val posts: StateFlow<List<Post>> = _posts
private val _isLoading = MutableStateFlow(false)
val isLoading: StateFlow<Boolean> = _isLoading
private val _error = MutableStateFlow<String?>(null)
val error: StateFlow<String?> = _error
init {
loadPosts()
}
fun loadPosts() {
viewModelScope.launch {
try {
_isLoading.value = true
_error.value = null
_posts.value = repository.getPosts()
} catch (e: Exception) {
_error.value = e.message
} finally {
_isLoading.value = false
}
}
}
}
APIから取得したデータを表示するViewを作成しましょう。
package com.example.jetpackhttpdemo
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.jetpackhttpdemo.data.Post
import com.example.jetpackhttpdemo.viewmodel.PostViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PostScreen(
modifier: Modifier = Modifier,
viewModel: PostViewModel = viewModel()
) {
val posts by viewModel.posts.collectAsState()
val isLoading by viewModel.isLoading.collectAsState()
val error by viewModel.error.collectAsState()
Column(modifier = modifier) {
TopAppBar(
title = { Text("Latest News") },
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary
)
)
Box(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp)
) {
if (isLoading) {
CircularProgressIndicator(
modifier = Modifier.align(Alignment.Center)
)
} else if (error != null) {
Text(
text = "Error: $error",
color = MaterialTheme.colorScheme.error,
modifier = Modifier
.align(Alignment.Center)
.padding(16.dp)
)
} else {
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(vertical = 16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
items(posts) { post ->
PostCard(post = post)
}
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PostCard(post: Post) {
Card(
modifier = Modifier.fillMaxWidth(),
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text(
text = post.title,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = post.body,
style = MaterialTheme.typography.bodyMedium
)
}
}
}
最後ににMainActivity.kt
でPostScreenを読み込めばデモアプリの完成です。
package com.example.jetpackhttpdemo
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.ui.Modifier
import com.example.jetpackhttpdemo.ui.theme.JetpackHttpDemoTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
JetpackHttpDemoTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
PostScreen(modifier = Modifier.fillMaxSize().padding(innerPadding))
}
}
}
}
}
ビルドに成功すれば期待する動作になっているはず
🙂最後に
今回は、libs.versions.toml retrofit & viewmodelのタイトルの通り新しいライブラリの追加方法でRetrofitとViewModelを使用する方法について解説いたしました。
以前とやり方が変わっているので焦りました(^_^;)
Discussion