$30 off During Our Annual Pro Sale. View Details »

Android Development Workshop

Android Development Workshop

This is a workshop that i gave to at the University of Johannesburg in 2018.
In 2019 I did a similar workshop, but the project we built was an API with Ktor.

https://github.com/pjwelcome/Ktor-StarterProject
https://github.com/pjwelcome/AndroidWorkshop

Peter-John Welcome

July 15, 2019
Tweet

More Decks by Peter-John Welcome

Other Decks in Programming

Transcript

  1. Android Development
    Workshop
    Peter-John Welcome
    @pjapplez
    Mobile Engineering Lead

    View Slide

  2. Day 1

    View Slide

  3. What we will do Today:
    Intro:
    1. Create our first Android app and run it.
    2. Git Crash Course
    3. Learn Kotlin for Android
    4. Crash Course on Android Layouts. (Constraint Layouts)
    5. RecyclerViews (View Holder Pattern)

    View Slide

  4. Let’s open Android Studio

    View Slide

  5. Android Dependencies
    dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
    implementation 'com.android.support:recyclerview-v7:27.1.1'
    }

    View Slide

  6. What is git?

    View Slide

  7. What is git?
    ● Git is an example of a DVCS (hence Distributed Version Control System)

    View Slide

  8. Kotlin

    View Slide

  9. Google announced Kotlin will be an official language for Android

    View Slide

  10. Why Kotlin over Java?
    ● Java is very verbose.
    ● Java Code is error prone with all its anonymous inner classes.
    ● Java lacks modern language features.
    ● Nullability issues.

    View Slide

  11. Language Features

    View Slide

  12. var/val
    var name : String = "Peter"
    name = "John"
    val surname = "Welcome"
    surname = "Johnson" // val can’t be reassigned

    View Slide

  13. Number one reason Android Apps
    Crash?

    View Slide

  14. Null Pointer Exception

    View Slide

  15. Nullability
    var name : String = "Peter"
    name = null // null can’t be a value on a non-null String
    var surname : String? = "Peter"
    surname = null
    val otherName = surname ?: "" // Elvis operator ( ?? in other languages)

    View Slide

  16. Classes

    View Slide

  17. Classes
    class User {
    private val name: String
    private val surname : String
    constructor(name : String , surname: String) {
    this .name = name
    this.surname = surname
    }
    }
    var user = User( surname = "Welcome", name = "Peter") // named arguments

    View Slide

  18. Data class
    @Parcelize
    data class Human (private var name: String, val age: Int) : Parcelable
    //copy, equal, hashcode, toString
    var human = Human("Peter",27)

    View Slide

  19. Sealed Classes
    sealed class Result{
    data class Success (val value : T) : Result()
    data class Error(val error : MyError) : Result()
    }

    View Slide

  20. Sealed Classes
    fun resultsFromService(result : Result) : String {
    when (result) {
    is Result.Success -> "${result.value} World"
    is Result.Error -> return result.error.toString()
    }
    return ""
    }
    resultsFromService(Result.Success("Hello"))

    View Slide

  21. Functions

    View Slide

  22. First class citizens

    View Slide

  23. High order functions

    View Slide

  24. Functions
    fun hello(){
    print("Hello")
    }
    val functionAsVariable = hello()
    val greetingPeter = fun (func : (name :String) -> String ) : String = func("Peter")
    greetingPeter {
    "Hello $it"
    }

    View Slide

  25. Extension functions

    View Slide

  26. Extension functions
    infix fun Int.add (value : Int) = this + value
    val result = 1.add(1)
    val result = 1 add 1
    //Extension function
    fun Observable.applySchedulers() : Observable =
    this.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
    //Usage
    disposable.add(this.viewModel.createPlant(Plant(name = "Best Plant
    Ever")).applySchedulers().subscribe ())

    View Slide

  27. Function Literals with Receiver

    View Slide

  28. Function Literals with Receiver
    inline fun SharedPreferences.edit(action: SharedPreferences.Editor.() -> Unit) {
    val editor = edit()
    editor.action()
    editor.apply()
    }
    getSharedPreferences("cache", Context.MODE_PRIVATE).edit {
    putString("username", "Peter")
    }

    View Slide

  29. Async Programming

    View Slide

  30. AsyncTasks
    class doAsyncTask(textView: TextView) : AsyncTask() {
    val innerTextView: TextView? = textView
    override fun doInBackground(vararg params: Unit?): String? {
    try {
    ...
    return data
    } catch (e: Exception) {
    return null
    }
    }
    override fun onPostExecute(result: String?) {
    super.onPostExecute(result)
    innerTextView?.text = JSONObject(result).toString()
    }
    }

    View Slide

  31. AsyncTasks

    View Slide

  32. RxJava
    disposable.add(viewModel.fetchDashboardPlants()
    .applySchedulers()
    .subscribe({
    //onNext:
    ...
    }, { error ->
    //onError
    })
    )
    fun Observable.applySchedulers() : Observable =
    this.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())

    View Slide

  33. Coroutines
    internal val background = newFixedThreadPoolContext(2, "background")
    launch (background) {
    val result = resultsFromService(Result.Success("Hello"))
    launch(UI) {
    this.textView.text = result
    }
    }
    // The async await way
    val someLongRunningTask = async(CommonPool) {
    return@async ""
    }.await()

    View Slide

  34. Let’s build our app.

    View Slide

  35. Life Cycles and Resources

    View Slide

  36. Layouts (Constraint Layout)

    View Slide

  37. RecyclerView

    View Slide

  38. RecyclerView

    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    android:id="@+id/rv_item_repo"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

    View Slide

  39. RecyclerView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    android:id="@+id/tv_animal_type"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginTop="48dp"
    android:layout_marginEnd="16dp"
    android:text="animal name"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

    View Slide

  40. RecyclerView
    class AnimalAdapter(val items: ArrayList) : RecyclerView.Adapter() {
    // Gets the number of animals in the list
    override fun getItemCount(): Int {
    return items.size
    }
    // Inflates the item views
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.animal_list_item, parent, false))
    }
    // Binds each animal in the ArrayList to a view
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.tvAnimalType.text = items.get(position)
    }
    }
    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    // Holds the TextView that will add each animal to
    val tvAnimalType = view.tv_animal_type
    }

    View Slide

  41. Slides
    https://tinyurl.com/ycb3cn7f
    Workshop Feedback
    https://bit.ly/2uFagmK

    View Slide