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

Building your first android app

Su Myat
November 30, 2021

Building your first android app

All you need to build your first ever android app

Su Myat

November 30, 2021
Tweet

More Decks by Su Myat

Other Decks in Programming

Transcript

  1. Hello Su Myat Senior Android Developer LOMOTIF Twitter : @SuMyatHtun9

    GDE for Android Women Teachmakers Ambassador Currently teaching myself compose
  2. OVERVIEW What we’ll talk about today 1. What you will

    need to know before you started create an android app ‣ What’s Android ?? ‣ language - google recommended programming for developing android apps. ‣ Android Studio - we use to write our code for android app 2. Sample Movie App in Action: let’s get our hands dirty ;)
  3. OVERVIEW What’s Android ‣ A mobile operation system that is

    developed by Google ‣ Support many different devices such as phones, tablets, tvs, wears and even cars. ‣ Demand very hight for Android career since most used mobile operating system in the world ‣ Easy to start - it’s probably easier than you think ‣ Easily find free courses such as videos, code labs, even real world projects
  4. WHAT YOU’LL NEED TO START BUILDING YOUR FIRST APP What

    you’ll need to develop apps ‣ You need a computer that’s powerful enough to run Android Studio ‣ You need stable internet connection ‣ You need to set up Android Studio in your computer ‣ You can start with even your programming in general
  5. For more detail: Go to the following link, and complete

    installing android studio on your computer Android Studio : https://bit.ly/3EgdmQs
  6. MAINLY TWO FACTS YOU NEED TO KNOW In App ‣

    Layout - describes how’s your app’s ui look like ‣ Buttons, TextViews, InputText, Image, etc.. ‣ Activities - behind the layout ‣ It tell your buttons or other views what to do
  7. WHAT YOU’LL NEED TO START BUILDING YOUR FIRST APP Variables

    in kotlin ‣ Val ‣ Things that don’t change like your birthday ‣ Var ‣ Things that can change such as your wearing clothes
  8. LET’S CREATE THIS APP ON HANDS class MainActivity : AppCompatActivity()

    { private var count = 0; override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val txtShowCount = findViewById<TextView>(R.id.txt_show_count) val btnCount = findViewById<Button>(R.id.btn_couting) btnCount.setOnClickListener { count++ txtShowCount.text = "Counting : ${count}" } } }
  9. YOU CAN CRATE WITH RELATIVELAYOUT TOO <RelativeLayout xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">

    <TextView android:id="@+id/txt_show_count" android:text="Counting .." android:layout_centerInParent="true"/> <Button android:id="@+id/btn_couting" android:text="Click me to count" android:layout_centerHorizontal="true" android:layout_below="@+id/txt_show_count"/> </RelativeLayout>
  10. LET’S CREATE THIS APP ON HANDS class MainActivity : AppCompatActivity()

    { private var count = 0; override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val txtShowCount = findViewById<TextView>(R.id.txt_show_count) val btnCount = findViewById<Button>(R.id.btn_couting) btnCount.setOnClickListener { count++ txtShowCount.text = "Counting : ${count}" } } }
  11. What you’ll need: Go to the following link, and access

    the sample project I created on GitHub : https://github.com/suhtun/amovie And branch out “develop” branch
  12. SAMPLE APP UI ‣ Retrofit for REST API communication ‣

    Coroutine for managing background thread ‣ ViewModel for store UI-related data that survive configuration changes such as rotate screen ‣ LiveData for Build data objects that notify views when the underlying database changes. ‣ Glide for image loading
  13. DEPENDENCIES // RecyclerView implementation 'androidx.recyclerview:recyclerview:1.3.0-alpha01' // Coil implementation "io.coil-kt:coil:1.4.0" //Retrofit

    implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.google.code.gson:gson:2.8.7' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1' //Coroutines implementation ‘org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2' //LifeCycle implementation 'androidx.lifecycle:lifecycle-common:2.4.0'
  14. ORGANISE OUR PACKAGES BY CATEGORY ‣ Utils for hold all

    helpers supporting code ‣ Ui for all UI related classes such as activity, adapter, ui model ‣ Repository handle data operation such as data from network or local storage ‣ network for all network code
  15. UTIL > STATUS ENUM CLASS REPRESENT THE UI STATE enum

    class Status { SUCCESS, ERROR, LOADING }
  16. UTIL> RESOURCE CLASS HOLDS A VALUE WITH IT’S STATUS data

    class Resource<out T>(val status: Status, val data: T?, val message: String?) { companion object { fun <T> success(data: T): Resource<T> = Resource(status = Status.SUCCESS, data = data, message = null) fun <T> error(data: T?, message: String): Resource<T> = Resource(status = Status.ERROR, data = data, message = message) fun <T> loading(data: T?): Resource<T> = Resource(status = Status.LOADING, data = data, message = null) } }
  17. Well done! ‣ Utils for hold all helpers supporting code

    ‣ Ui for all UI related classes such as activity, adapter, ui model ‣ Repository handle data operation such as data from network or local storage ‣ network for all network code
  18. DATA> NETWORK OUR REST API JSON WILL BE LIKE data

    class PlayingMoviewsResponse( @SerializedName("results") val movieResults: List<MovieResult> ) data class MovieResult( @field:SerializedName("popularity") val popularity: Double, @field:SerializedName("poster_path") val poster_path: String, @field:SerializedName(“id”) val id: String, @field:SerializedName(“vote_average”) val vote_average: String, @field:SerializedName(“overview”) val overview: String, @field:SerializedName("release_date") val release_date: String )
  19. API> APISERVICE HOLDS ALL REST API interface ApiService { @GET("now_playing?page=1")

    suspend fun getPlayingMovie(): PlayingMoviewsResponse }
  20. API> BUILD RETROFIT FOR YOUR REST APIS object RetrofitBuilder {

    private const val BASE_URL = "https://api.themoviedb.org/3/movie/" private fun getRetrofit(): Retrofit { return Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build() } val apiService: ApiService = getRetrofit().create(ApiService::class.java) }
  21. Well done! we completed network part from data package ‣

    Utils for hold all helpers supporting code ‣ Ui for all UI related classes such as activity, adapter, ui model ‣ Repository handle data operation such as data from network or local storage ‣ network for all network code
  22. DATA> REPOSITORY class MainRepository(private val apiService: ApiService) { suspend fun

    getMovies() = apiService.getPlayingMovie().movieResults .map { MovieUiModel( it.id, it.poster_path, it.original_title, it.release_date ) } }
  23. DATA> REPOSITORY class MainRepository(private val apiService: ApiService, ) { suspend

    fun getMovies() = apiService.getPlayingMovie().movieResults .map { MovieUiModel( it.id, it.poster_path, it.original_title, it.release_date ) } }
  24. Well done! we completed network part from data package ‣

    Utils for hold all helpers supporting code ‣ Ui for all UI related classes such as activity, adapter, ui model ‣ Repository handle data operation such as data from network or local storage ‣ network for all network code
  25. UI > MAIN FEATURE > VIEWMODEL class MainViewModel(private val mainRepository:

    MainRepository) : ViewModel() { val movies : LiveData<Resource<List<MovieUiModel>>> = getMoviesData() private fun getMoviesData() = liveData(Dispatchers.IO) { emit(Resource.loading(data = null)) try { emit(Resource.success(data = mainRepository.getMovies())) } catch (exception: Exception) { emit(Resource.error(data = null, message = exception.message ? "Error Occurred!")) } } }
  26. LAYOUT> MOVIE CARD ITEM LAYOUT <?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView 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:id="@+id/cardview"> <LinearLayout> <ImageView android:id="@+id/img_movie"/> <TextView android:id="@+id/txt_movie_name"/> <TextView android:id="@+id/txt_movie_release_date"/> </LinearLayout> </androidx.cardview.widget.CardView>
  27. LAYOUT> show movie list view <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/androi xmlns:tools="http://schemas.android.com/tools" tools:context=".ui.main.MainActivity"> <androidx.recyclerview.widget.RecyclerView

    android:id="@+id/recycler_view"/> <ProgressBar android:id="@+id/progress_bar" style="?android:attr/progressBarStyle" android:layout_centerInParent="true"/> <TextView android:id="@+id/txt_error_msg" android:layout_below="@+id/progress_bar" android:layout_centerInParent="true"/> </RelativeLayout>
  28. UI> CREATE YOUR ADAPTER FOR MOVIES SCREEN class MovieAdapter(..) :RecyclerView.Adapter<..>()

    { class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){} override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.movie_item, parent, false) return MovieViewHolder(view) } override fun getItemCount() = movies.size override fun onBindViewHolder(holder: FlowerViewHolder, position: Int) }
  29. UI>MAIN> setting up recyclerview UI private lateinit var adapter: MovieAdapter

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setupUI() } private fun setupUI() { val recyclerView: RecyclerView = findViewById(R.id.recycler_view) val gridLayoutManager = GridLayoutManager(this, 3) recyclerView.layoutManager = gridLayoutManager adapter = MovieAdapter(arrayListOf()) recyclerView.adapter = adapter }
  30. UI>MAIN> setting up view model private lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setupViewModel() } private fun setupViewModel() { viewModel = ViewModelProvider(this, ViewModelFactory(MainRepository(RetrofitBuilder.apiService)) .get(MainViewModel::class.java) }
  31. UI > MAIN FEATURE > VIEWMODEL private fun setupObservers() {

    viewModel.movies.observe(this, Observer { it?.let { resource -> when (resource.status) { Status.SUCCESS -> { progressBar.visibility = View.GONE txtErrorMessage.visibility = View.GONE resource.data?.let { movies ->retrieveList(movies)) } } Status.ERROR -> {hide loading bar and show error msg} Status.LOADING -> {//show loading bar} } } }) }
  32. WELL DONE! ‣ You will see this movies screen on

    your test phone after you build ‣ Keep learning: https://classroom.udacity.com/courses/u d9012 https://developer.android.com/courses/a ndroid-basics-kotlin/course ‣ https://github.com/android/views-widgets -samples