Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

7cfaab5ac5113201604c3ad16d9a293b?s=128

Peter-John Welcome

July 15, 2019
Tweet

Transcript

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

  2. Day 1

  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)
  4. Let’s open Android Studio

  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' }
  6. What is git?

  7. What is git? • Git is an example of a

    DVCS (hence Distributed Version Control System)
  8. Kotlin

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

  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.
  11. Language Features

  12. var/val var name : String = "Peter" name = "John"

    val surname = "Welcome" surname = "Johnson" // val can’t be reassigned
  13. Number one reason Android Apps Crash?

  14. Null Pointer Exception

  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)
  16. Classes

  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
  18. Data class @Parcelize data class Human (private var name: String,

    val age: Int) : Parcelable //copy, equal, hashcode, toString var human = Human("Peter",27)
  19. Sealed Classes sealed class Result<out T>{ data class Success<out T>

    (val value : T) : Result<T>() data class Error(val error : MyError) : Result<MyError>() }
  20. Sealed Classes fun <T>resultsFromService(result : Result<T>) : String { when

    (result) { is Result.Success -> "${result.value} World" is Result.Error -> return result.error.toString() } return "" } resultsFromService(Result.Success("Hello"))
  21. Functions

  22. First class citizens

  23. High order functions

  24. Functions fun hello(){ print("Hello") } val functionAsVariable = hello() val

    greetingPeter = fun (func : (name :String) -> String ) : String = func("Peter") greetingPeter { "Hello $it" }
  25. Extension functions

  26. Extension functions infix fun Int.add (value : Int) = this

    + value val result = 1.add(1) val result = 1 add 1 //Extension function fun <T> Observable<T>.applySchedulers() : Observable<T> = this.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) //Usage disposable.add(this.viewModel.createPlant(Plant(name = "Best Plant Ever")).applySchedulers().subscribe ())
  27. Function Literals with Receiver

  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") }
  29. Async Programming

  30. AsyncTasks class doAsyncTask(textView: TextView) : AsyncTask<Unit, Unit, String>() { 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() } }
  31. AsyncTasks

  32. RxJava disposable.add(viewModel.fetchDashboardPlants() .applySchedulers() .subscribe({ //onNext: ... }, { error ->

    //onError }) ) fun <T> Observable<T>.applySchedulers() : Observable<T> = this.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
  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<String>(CommonPool) { return@async "" }.await()
  34. Let’s build our app.

  35. Life Cycles and Resources

  36. Layouts (Constraint Layout)

  37. RecyclerView

  38. RecyclerView <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout 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.support.v7.widget.RecyclerView android:id="@+id/rv_item_repo" android:layout_width="match_parent" android:layout_height="match_parent" /> </android.support.constraint.ConstraintLayout>
  39. RecyclerView <android.support.constraint.ConstraintLayout 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"> <TextView 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" /> </android.support.constraint.ConstraintLayout>
  40. RecyclerView class AnimalAdapter(val items: ArrayList<String>) : RecyclerView.Adapter<ViewHolder>() { // 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 }
  41. Slides https://tinyurl.com/ycb3cn7f Workshop Feedback https://bit.ly/2uFagmK