-
Notifications
You must be signed in to change notification settings - Fork 0
Lab 12
Use Retrofit and Moshi to load JSON data from a network api.
- Retrofit is a popular HTTP client for Android and Java. It will generate a working network client based on service definition interfaces you provide it. In this lab, we will use Retrofit to fetch a list of study topics from a network api.
- Moshi is a JSON serialization library that works very well with Kotlin. We can use Moshi, in conjunction with Retrofit, to deserialize our network responses.
- Both Retrofit and Moshi use annotations to generate working implementations for us. Retrofit uses those annotations to inform its reflection-based processing of the service definition to provide a working network client. Moshi must use either an annotationProcessor such as
kapt
(kotlin annotation processor) or, as in the case of this project,ksp
(kotlin symbol processing).
-
Open
AndroidManifest.xml
and add<uses-permission android:name="android.permission.INTERNET" />
-
Create a new package named
network
-
In the
network
package, create an interface namedStudyGuideService
-
Add a method to
StudyGuideService
calledgetTopics()
that is a suspending function and returns aList<Topic>
- To make a Kotlin function a suspending function, add the
suspend
keyword before thefun
keyword - Suspending functions are a core part of Kotlin's coroutine apis.
- Suspending functions are functions that may be paused ("suspended") and resumed at a later point - without blocking the current
Thread
- Suspending functions allow us to write asynchronous code in an imperative way. Our suspending function may be called, and then paused while it waits for some aysnc operation such as a network or database result. Once that result is returned, our suspending function may then continue on with the rest of its operations.
- For a more detailed example of suspending functions, see this guide.
- To make a Kotlin function a suspending function, add the
-
Add the following annotation to the
Topic
class:@JsonClass(generateAdapter = true)
- This annotation will indicate to Moshi that it should generate a Json adapter automatically
- Moshi is a serialization library that has strong support for Kotlin
- Using Moshi will help us deserialize network responses
-
Add the base endpoint url to your user directory's
.gradle/gradle.properties
file- Navigate to your computer's current user directory
- You'll want to open the
.gradle
directory. - Open, or create if it doesn't exist, the
gradle.properties
file - Within that file, add the following
STUDY_GUIDE_SERVICE_URL=<end point url from instructor>
- Within Android Studio, re-sync your project, then rebuild your project
- This should result in a new
BuildConfig
property being generated that allows us to use this endpoint url without having to check it into our codebase
-
We need to create an instance of
Retrofit.Builder
to generate a working network client- Open
StudyGuideService.kt
- Create a top-level property named
studyGuideService
and initialize it toRetrofit.Builder().build()
- Before the
.build()
call, add a call tobaseUrl(BuildConfig.STUDY_GUIDE_SERVICE_URL)
- After setting the base url, add a json converter factory with
.addConverterFactory(MoshiConverterFactory.create())
- Open
-
After calling
.build()
onRetrofit.Builder
, create an instance of theStudyGuideService
interface by calling.create(StudyGuideService::class.java)
-
Within the
init{}
ofStudyGuideViewModel
, replace the current implementation with one that uses the new Retrofit service to load the topics
- You can add a new property to your
UiState
class to represent the loading state of the screen - Make the loading property default to true
- In
StudyGuideFragment
update your layout, and code, to show an indeterminate progress bar (a progress bar that just spins indefinitely)- In
fragment_study_guide.xml
addcom.google.android.material.progressindicator.CircularProgressIndicator
after theRecyclerView
- Constrain it to fit in the middle of the screen
- Add
android:visibility="visible"
- Add
android:indeterminate="true"
- Add
app:indicatorColor="?colorPrimary"
andapp:trackColor="?colorSecondary"
to update the styling
- In
Open your AndroidManifest.xml
file, and add the permission declaration as follows:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="dev.goobar.androidstudyguide">
<uses-permission android:name="android.permission.INTERNET" />
<application>
...
</application>
</manifest>
The BuildConfig.STUDY_GUIDE_SERVICE_URL
property is generated based on the presence of a local Gradle property.
We don't just hardcode this value, because we want the url to be more secure to help avoid unwanted use.
The app/build.gradle
file is already configured to generate this value if STUDY_GUIDE_SERVICE_URL
is present in either the project's gradle.properties
file or your user directory's .gradle/gradle.properties
file.
If you are having trouble generating this value, make sure that the Gradle property is set.
It should look something like STUDY_GUIDE_SERVICE_URL="<service url>"
If you don't know what the URL should be, contact the instructor.
val studyGuideService = Retrofit.Builder()
.baseUrl(BuildConfig.STUDY_GUIDE_SERVICE_URL)
.addConverterFactory(MoshiConverterFactory.create())
.build()
.create(StudyGuideService::class.java)
Update the init{}
block of the view model to launch a new coroutine in a background Thread
, make a call to studyGuideService.getTopics()
, and finally update the UiState
.
viewModelScope.launch(Dispatchers.IO) {
val topics = studyGuideService.getTopics()
state.update { currentValue -> UiState(topics) }
}