Lab 5A: Swift Repos (Android)
Due Date: October 06
Objectives
- introduce table views
- teach students how to build and use item lists
- reinforce skills related to API handling and JSON
- provide a soft launch to concepts of reactive programming
Due Date: October 06
Objectives
In this lab, we will build an application to look at the most popular Swift repositories on GitHub using the GitHub API and many of the skills we have learned in class. The final application will look something like this:
In Android Studio create a new project and select the "No Activity" template. Give your project a name of SwiftRepos. Make sure you select Kotlin as your language. Once your project base loads, open build.gradle.kts
(module :app). Set the compileSDK and targetSDK to '34' and re-run the gradle project sync.
In your main package/project directory, create a new "Primary/Detail Views Flow" Activity (File > New > Activity > Primary/Detail..."). Select the launcher activity checkbox and make sure the package name is correct. Build and run the project and take a look at what it is doing. Examine a few files especially PlaceholderContent.kt
.
Open the file item_list_content.xml and change the android:orientation="horizontal"
to android:orientation="vertical"
. Run the project again and see what changed.
Add the following permission to AndroidManifest.xml
inside the manifest tag and before the application tag:
<uses-permission android:name="android.permission.INTERNET" />
Add the following dependencies to the modules gradle build script:
implementation 'com.android.volley:volley:1.1.1'
implementation 'com.google.android.gms:play-services-auth:18.1.0'
implementation 'com.google.code.gson:gson:2.8.6'
Volley is a library we will use to perform our JSON queries. Gson is a library for (de)serializing (encoding/decoding) json objects to java/kotlin objects. We’ll need google play services in order to ensure our SSL certs are up to date.
Repo.kt
and Item.kt
data class Repo (val total_count : Int,
val incomplete_results : Boolean,
val items : Array<Item>)
data class Item (val id : Int,
val node_id : String,
val name : String,
val full_name : String,
val description :String,
val homepage : String
){
override fun toString(): String = full_name + "\n" + description + "\n" + homepage
}
Notice that the json query we will run, provides many more fields that our data classes contain. That is fine. Gson will ignore everything we do not tell it specifically to save. It is possible to change the names of these variables when parsing but that is an extra step that we will not concern ourselves with.
Android studio will give a warning that the Items ArrayList in Repo makes it so that Repo’s can’t be compared. This is because ArrayLists are not a primitive type requiring additional handling. You can add this logic using Studio’s recommendations but it is not necessary for this lab.
Performing url queries in kotlin can be as simple as let result = URL("website").readText()
however, if the result is larger than a few lines (or you have slow internet) this will hang your program, and potentially will cause it’s startup to timeout and thereby crash. This is where Volley comes in handy.
Open up the ItemListActivity.kt
. Comment out the setupRecyclerView
function call at the end of onCreate
. Run the program and see what happens.
Add the following to the end of onCreate
:
ProviderInstaller.installIfNeeded(applicationContext)
val cache = DiskBasedCache(cacheDir, 1024 * 1024) // 1MB cap
val network = BasicNetwork(HurlStack())
val queue = RequestQueue(cache, network).apply {
start()
}
The ProviderInstaller
update tells google play services to allow the valid cert from github. The other lines of code are preparing for the network calls to come later.
Now create a kotlin object similar to DummyContent.kt
called Content.kt
(you can just refactor DummyContent but recall we already made a data class for Item). Make addItem
public and remove the initial population of example data. Fun fact about kotlin objects, they’re all Singletons. This goes for companion objects as well.
Add the following code to the end of ItemListActivity.kt
’s onCreate function.
val url = "https://api.github.com/search/repositories?q=language:swift&sort=stars&order=desc"
val jsonObjectRequest = JsonObjectRequest(Request.Method.GET, url, null,
{ response ->
val gson = Gson()
val repo = gson.fromJson<Repo>(response.toString(),Repo::class.java)
Log.d("JSON",repo.items[0].id.toString())
Log.d("JSON",repo.items[0].name)
Log.d("JSON",repo.items[0].homepage)
},
{ error ->
Log.d("JSON", error.message!!)
}
)
queue.add(jsonObjectRequest)
This code is self-explanatory with two standouts. The Log.d
commands allow you to print to the debugging logs console. You should see the first item from the json query there next to a header that reads "JSON". This makes it very easy to search the debugger to find the output you want. The other neat feature is gson.fromJson<Repo>(response.toString(),Repo::class.java)
. As you might expect this turns our json string into a variable of type Repo
but it also translated the item objects to be of type Item
automatically.
val items:ArrayList<Item> = repo.items.toCollection(ArrayList())
items.forEach { i -> Content.addItem(i) }
setupRecyclerView(findViewById(R.id.item_list),items)
setupRecyclerView is called now because calling it outside this code block would make it run earlier. Here it only runs at the end of a valid request and only once all the querying and parsing has taken place.
Now you have a working JSON query, translated into data classes, stored in an object, and a View that is being populated by that data. All you have to do now is make sure all of the wires are connected, T's are crossed, and buttons are working. You will find two additional buttons left over from the template that when pressed say to add in functionality. This is something you can do on your own like perhaps adding a search capability.
If time allows, you can also explore customizing the views more and cleaning up some of the code. Feel free to explore further--that's where the real fun and learning is!
Qapla'