This assignment has a release code! Please download it below, extract it, and open it in Android Studio. Ensure it can compile and run fine on your emulator before starting this assignment.
For our final assignment, we'll have you develop the networking logic for a basic fitness app!
Rounding out our journey away from money and towards happiness, of course we have to take a stop by physical wellness.
Let's walk through the code, shall we?
Release Code
Expand each of the files below for a description of the release code!
main package
Contains the home screen / main screen logic. Pertains just to part 0).
Overall, this screen gives the option for the user to input an exercise name as well as choose some tags about their exercise.
results package
Contains the search results screen logic. Pertains to parts 4) and 5).
This screen shows the results of a successful networking--a scrollable horizontal pager of exercises that match the search results.
retrofit package
Contains empty Retrofit files you'll have to implement in 2) and 3)!
ExerciseCard.kt
A card that displays information about one exercise. This corresponds to all the information that our API will return:
Knob.kt
A tappable knob that is used for tags. This will be used in the main screen to allow the user to select certain tags about their exercise search:
Requirements:
This assignment is not split into features, but rather more so as steps towards implementing Retrofit correctly.
0) Main Warmup
Time for a bit of a warmup to make sure you understand the codebase (and MVVM)!
You'll notice that none of the buttons nor the text field work yet on the main screen. Let's fix that using our UiState class and the uiStateFlow!
Connect the query and onQueryChanged(...) from MainViewModel to the MainScreen.
Do the same such that Training Type and Muscle Group tags change correctly when they're tapped on!
(Make it so that the Knob with the current trainingType/muscleGroup is set to active = true, false otherwise.)
1) API Ninjas Setup
For our backend for this assignment, we would like you to make an account on API Ninjas and access their Exercises API. It's free!
In essence, this endpoint will return a list of (at most 5) exercises matching some parameters we put in. Our app will allow users to (optionally) put in a name, a training type, and a muscle group.
2) Retrofit Dependencies
Add the following dependencies to your build.gradle :app file.
Gradle Sync your project. There should be no build errors (hopefully...)
3) ExerciseApiService.kt
Time to use Retrofit to implement a networking call for us!
We'll be hitting the https://api.api-ninjas.com/v1/exercises endpoint. Note that this is NOT the link you manually want to visit to read the api; this is a unique link used to actually make networking calls to.
Make a @GET suspend function called getExercises(...) that uses the "exercises" route.
Give this function 3 optional string arguments: name, type, and muscle. These should be annotated as @Query parameters under the same name.
replace YOUR_API_KEY_HERE with the key API Ninjas gave to you upon signup!
Referencing the JSON that API Ninjas gives to you on their exercises api page, make a Exercise data class that accepts 6 string fields (corresponding to the JSON fields).
Change the return type of your function to a List<Exercise>.
4) RetrofitInstance.kt
Time to set our URL and other parameters with our RetrofitInstance class!
Implement RetrofitInstance with the correct API base URL. Please note that "exercises" is the extension of the URL; the base URL is just https://api.api-ninjas.com/v1/
Make this correctly into a hilt singleton that can then be injected into other hilt references. This also involves adding the @Inject constructor notation.
Inject the retrofitInstance into ResultsViewModel.
Please reference our demo code to how see how this is done! You should make a exerciseApiService field, or something similar.
5) ResultsViewModel & Networking
Alright, time to tie it all together! In this part, you'll implement and test final the networking logic to get your app actually showing the proper response from the backend.
Implement loadData() by using your retrofitInstance in the launched coroutine:
Make a call to your getExercises(...) . Make sure you pass in the query, trainingType, and muscleGroup parameters we extracted for you from the navigation arguments!
When the call terminates, set the UiState loading to false.
Test the app! You should no longer see the app infinitely load.
Add another field to your UiState class that sends down the (loaded) list of exercises to the UI.
The call to getExercises(...) should have returned the list of exercises; make sure to actually send this down your UiState flow.
Edit ResultsScreen and ExerciseCard to actually send down each exercise's information to the card.
Also, make sure that the pager is showing the right number of cards; it is hardcoded to 3 right now.
You can choose to just delete the @Preview for exercise card if you want, or edit it to allow the preview to continue showing!
(Don't worry too much about the particulars about how the text is rendered. You won't be graded about the nitpicky stuff.)
If you get any networking errors, make sure to debug with LogCat errors!
If you've solved A6 correctly, your solution should look something like this...
When you're done, export your project through Android Studio and upload your ZIP to CMS! Congrats on finishing A6--the final assignment of Intro to Android!