Site icon C1CTech

Android MVVM Pattern with Retrofit in Kotlin

&NewLine;<p>This post is about the MVVM pattern in Android&comma; and how to build a project with the MVVM pattern using Retrofit&period;<&sol;p> &NewLine; &NewLine; &NewLine; &NewLine;<div class&equals;"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-a89b3969 wp-block-buttons-is-layout-flex"> &NewLine;<div class&equals;"wp-block-button"><a class&equals;"wp-block-button&lowbar;&lowbar;link has-background" style&equals;"background-color&colon; &num;240372&semi;" href&equals;"https&colon;&sol;&sol;github&period;com&sol;arunk7839&sol;MVVMWithNetworkSource"><strong>DOWNLOAD CODE<&sol;strong><&sol;a><&sol;div> &NewLine;<&sol;div> &NewLine;<h4> <&sol;h4> &NewLine;<p><amp-youtube layout&equals;"responsive" width&equals;"1200" height&equals;"675" data-videoid&equals;"rh2ZBEOHXVk" title&equals;"Android MVVM Pattern with Retrofit in Kotlin"><a placeholder href&equals;"https&colon;&sol;&sol;youtu&period;be&sol;rh2ZBEOHXVk"><img src&equals;"https&colon;&sol;&sol;i&period;ytimg&period;com&sol;vi&sol;rh2ZBEOHXVk&sol;hqdefault&period;jpg" layout&equals;"fill" object-fit&equals;"cover" alt&equals;"Android MVVM Pattern with Retrofit in Kotlin"><&sol;a><&sol;amp-youtube><&sol;p> &NewLine;<h4><span style&equals;"color&colon; &num;000080&semi;"><strong>What is MVVM&quest;<&sol;strong><&sol;span><&sol;h4> &NewLine;<ul> &NewLine;<li>MVVM architecture is a <strong><span style&equals;"color&colon; &num;008000&semi;">Model-View-ViewModel<&sol;span> <&sol;strong>architecture&period;<&sol;li> &NewLine;<li>It allows separating the user interface logic from the business &lpar;or the back-end&rpar; logic&period;<&sol;li> &NewLine;<li>Its target is to keep UI code simple and free of app logic in order to make it easier to manage and test&period; <&sol;li> &NewLine;<&sol;ul> &NewLine;<p>MVVM has mainly the following layers&colon;<&sol;p> &NewLine;<p><span style&equals;"color&colon; &num;000080&semi;"><strong>Model<&sol;strong><&sol;span>&colon;<&sol;p> &NewLine;<p>The model represents the data and the business logic of the Application&period; It consists of the business logic &&num;8211&semi; local and remote data source&comma; model classes&comma; repository&period;<&sol;p> &NewLine;<p><strong><span style&equals;"color&colon; &num;000080&semi;">View<&sol;span><&sol;strong>&colon;<&sol;p> &NewLine;<p>The view consists of the UI Code&lpar;Activity&comma; Fragment&rpar;&comma; XML&period; The view role in this pattern is to observe &lpar;or subscribe to&rpar; a ViewModel observable to get data in order to update UI elements accordingly&period;<&sol;p> &NewLine;<p><strong><span style&equals;"color&colon; &num;000080&semi;">ViewModel<&sol;span><&sol;strong>&colon; <&sol;p> &NewLine;<p>ViewModel interacts with the model and also prepares observable&lpar;s&rpar; that can be observed by a View&period; <br &sol;>One of the important implementation strategies of this layer is to decouple it from the View&comma; i&period;e&comma; ViewModel should not be aware of the view who is interacting with&period;<&sol;p> &NewLine;<h4><span style&equals;"color&colon; &num;000080&semi;"><strong>Creating new project<&sol;strong><&sol;span><&sol;h4> &NewLine;<p>1 &period; Create a new project by going to <span style&equals;"color&colon; &num;008000&semi;"><strong>File &Implies; New Android Project<&sol;strong><&sol;span>&comma; select <span style&equals;"color&colon; &num;008000&semi;"><strong>Empty<&sol;strong><&sol;span> Activity&comma; provide <span style&equals;"color&colon; &num;008000&semi;"><strong>app<&sol;strong><&sol;span> name&comma; select language to <span style&equals;"color&colon; &num;008000&semi;"><strong>kotlin<&sol;strong><&sol;span> and then finally click on <span style&equals;"color&colon; &num;0000ff&semi;"><strong>finish<&sol;strong><&sol;span>&period;<&sol;p> &NewLine;<p>2 &period; Open app-level build&period;gradle file and add the below changes&colon;<&sol;p> &NewLine;<ul> &NewLine;<li>Add the below libraries under the <span style&equals;"color&colon; &num;008000&semi;"><strong>dependencies<&sol;strong><&sol;span> section<strong>&colon;<&sol;strong><&sol;li> &NewLine;<&sol;ul> &NewLine;<pre>dependencies &lbrace;<br &sol;><strong><span style&equals;"color&colon; &num;008000&semi;"> &sol;&sol;ViewModel and livedata<&sol;span><&sol;strong><br &sol;> implementation "androidx&period;lifecycle&colon;lifecycle-extensions&colon;2&period;2&period;0"<br &sol;><br &sol;><span style&equals;"color&colon; &num;008000&semi;"><strong> &sol;&sol;Retrofit<&sol;strong><&sol;span><br &sol;> implementation 'com&period;squareup&period;retrofit2&colon;retrofit&colon;2&period;9&period;0'<br &sol;> implementation 'com&period;squareup&period;retrofit2&colon;converter-gson&colon;2&period;9&period;0'<br &sol;><br &sol;><strong><span style&equals;"color&colon; &num;008000&semi;"> &sol;&sol;Glide<&sol;span><&sol;strong><br &sol;> implementation 'com&period;github&period;bumptech&period;glide&colon;glide&colon;4&period;12&period;0'<br &sol;> implementation 'com&period;github&period;bumptech&period;glide&colon;compiler&colon;4&period;12&period;0'<br &sol;>&rcub;<&sol;pre> &NewLine;<ul> &NewLine;<li>Inside the android block&comma; add viewBinding block with property enabled to true&period;<&sol;li> &NewLine;<&sol;ul> &NewLine;<pre>viewBinding &lbrace;<br &sol;> enabled &equals; true<br &sol;>&rcub;<&sol;pre> &NewLine;<ul> &NewLine;<li>Finally&comma; click on <strong><span style&equals;"color&colon; &num;0000ff&semi;">Sync Now&period;<&sol;span><&sol;strong><&sol;li> &NewLine;<&sol;ul> &NewLine;<p>3&period; Open the AndroidManifest&period;xml file and add the internet permission above the application element&period;<&sol;p> &NewLine;<pre>&lt&semi;uses-permission android&colon;name&equals;"android&period;permission&period;INTERNET"&sol;&gt&semi;<&sol;pre> &NewLine;<h4><span style&equals;"color&colon; &num;000080&semi;"><strong>Setup the Data Layer<&sol;strong><&sol;span><&sol;h4> &NewLine;<p>In the data layer&comma; we have to prepare the model for the data&comma; and an API call needs to be implemented&period; <&sol;p> &NewLine;<h5><span style&equals;"color&colon; &num;0000ff&semi;"><strong>Creating Model class<&sol;strong><&sol;span><&sol;h5> &NewLine;<p>I will use<span style&equals;"color&colon; &num;008000&semi;"> <strong>&&num;8220&semi;https&colon;&sol;&sol;fake-movie-database-api&period;herokuapp&period;com&sol;api&quest;s&equals;batman&&num;8221&semi;<&sol;strong><&sol;span> API to fetch the data&period;<&sol;p> &NewLine;<p>The API JSON response will be like this&period;<&sol;p> &NewLine;<pre>&lbrace;<br &sol;>"Search"&colon; &lbrack;<br &sol;>&lbrace;<br &sol;>"imdbID"&colon; "tt0096895"&comma;<br &sol;>"Title"&colon; "Batman"&comma;<br &sol;>"Year"&colon; "1989"&comma;<br &sol;>"Poster"&colon; "https&colon;&sol;&sol;images-na&period;ssl-images-amazon&period;com&sol;images&sol;M&sol;MV5BMTYwNjAyODIyMF5BMl5BanBnXkFtZTYwNDMwMDk2&period;&lowbar;V1&lowbar;&period;jpg"<br &sol;>&rcub;&comma;<br &sol;>&lbrace;<br &sol;>"imdbID"&colon; "tt0468569"&comma;<br &sol;>"Title"&colon; "The Dark Knight"&comma;<br &sol;>"Year"&colon; "2008"&comma;<br &sol;>"Poster"&colon; "https&colon;&sol;&sol;ia&period;media-imdb&period;com&sol;images&sol;M&sol;MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw&commat;&commat;&period;&lowbar;V1&lowbar;UX182&lowbar;CR0&comma;0&comma;182&comma;268&lowbar;AL&lowbar;&period;jpg"<br &sol;>&rcub;&comma;<br &sol;>&period;&period;&period;&period;<br &sol;>&rsqb;<br &sol;>&rcub;<&sol;pre> &NewLine;<p>For the response data&comma; we need to create the below two model classes&period;<&sol;p> &NewLine;<p><span style&equals;"color&colon; &num;0000ff&semi;"><strong>MovieList&period;kt<&sol;strong><&sol;span><&sol;p> &NewLine;<pre>import com&period;c1ctech&period;mvvmwithnetworksource&period;Movie<br &sol;>import com&period;google&period;gson&period;annotations&period;SerializedName<br &sol;><br &sol;>data class MovieList&lpar;&commat;SerializedName&lpar;"Search"&rpar; val mList &colon; List&lt&semi;Movie&gt&semi;&rpar;<&sol;pre> &NewLine;<p><span style&equals;"color&colon; &num;0000ff&semi;"><strong>Movie&period;kt<&sol;strong><&sol;span><&sol;p> &NewLine;<pre>import com&period;google&period;gson&period;annotations&period;SerializedName<br &sol;><br &sol;>data class Movie&lpar;<br &sol;> &commat;SerializedName&lpar;"Title"&rpar; val title&colon; String&comma;<br &sol;> &commat;SerializedName&lpar;"Poster"&rpar; val poster&colon; String&comma;<br &sol;> val imdbID&colon; String&comma;<br &sol;> &commat;SerializedName&lpar;"Year"&rpar; val year&colon; String<br &sol;>&rpar;<&sol;pre> &NewLine;<h5><span style&equals;"color&colon; &num;0000ff&semi;"><strong>Setting up Retrofit<&sol;strong><&sol;span><&sol;h5> &NewLine;<p>Create an interface <strong><span style&equals;"color&colon; &num;008000&semi;">RetrofitService<&sol;span><&sol;strong> for the API call&period;<&sol;p> &NewLine;<p><span style&equals;"color&colon; &num;0000ff&semi;"><strong>RetrofitService&period;kt<&sol;strong><&sol;span><&sol;p> &NewLine;<pre>import com&period;c1ctech&period;mvvmwithnetworksource&period;model&period;MovieList<br &sol;>import retrofit2&period;Call<br &sol;>import retrofit2&period;Retrofit<br &sol;>import retrofit2&period;converter&period;gson&period;GsonConverterFactory<br &sol;>import retrofit2&period;http&period;GET<br &sol;><br &sol;>interface RetrofitService &lbrace;<br &sol;> &commat;GET&lpar;"api&quest;s&equals;batman"&rpar;<br &sol;> fun getAllMovies&lpar;&rpar;&colon; Call&lt&semi;MovieList&gt&semi;<br &sol;><br &sol;> companion object &lbrace;<br &sol;><br &sol;> var retrofitService&colon; RetrofitService&quest; &equals; null<br &sol;><br &sol;><strong><span style&equals;"color&colon; &num;008000&semi;"> &sol;&sol;Create the Retrofit service instance using the retrofit&period;<&sol;span><&sol;strong><br &sol;> fun getInstance&lpar;&rpar;&colon; RetrofitService &lbrace;<br &sol;><br &sol;> if &lpar;retrofitService &equals;&equals; null&rpar; &lbrace;<br &sol;> val retrofit &equals; Retrofit&period;Builder&lpar;&rpar;<br &sol;> &period;baseUrl&lpar;"https&colon;&sol;&sol;fake-movie-database-api&period;herokuapp&period;com&sol;"&rpar;<br &sol;> &period;addConverterFactory&lpar;GsonConverterFactory&period;create&lpar;&rpar;&rpar;<br &sol;> &period;build&lpar;&rpar;<br &sol;> retrofitService &equals; retrofit&period;create&lpar;RetrofitService&colon;&colon;class&period;java&rpar;<br &sol;> &rcub;<br &sol;> return retrofitService&excl;&excl;<br &sol;> &rcub;<br &sol;> &rcub;<br &sol;>&rcub;<&sol;pre> &NewLine;<h5><span style&equals;"color&colon; &num;0000ff&semi;"><strong>Setup Data Repository<&sol;strong><&sol;span><&sol;h5> &NewLine;<p>Inside the below repository class&comma; we need to pass the retrofit service instance to perform the network call&period; The repository class will only interact with the network source&comma; the response of the network call we will handle later in ViewModel&period;<&sol;p> &NewLine;<p><strong><span style&equals;"color&colon; &num;0000ff&semi;">MainRepository&period;kt<&sol;span><&sol;strong><&sol;p> &NewLine;<pre>import com&period;c1ctech&period;mvvmwithnetworksource&period;RetrofitService<br &sol;><br &sol;>class MainRepository constructor&lpar;private val retrofitService&colon; RetrofitService&rpar; &lbrace;<br &sol;><br &sol;> fun getAllMovies&lpar;&rpar; &equals; retrofitService&period;getAllMovies&lpar;&rpar;<br &sol;>&rcub;<&sol;pre> &NewLine;<h4><span style&equals;"color&colon; &num;000080&semi;"><strong>Setup the ViewModel<&sol;strong><&sol;span><&sol;h4> &NewLine;<p>The MainViewModel class extends the ViewModel&period; <&sol;p> &NewLine;<p>In the ViewModel constructor&comma; we need to pass the data repository to handle the response from the API call&period;<&sol;p> &NewLine;<p>It uses LiveData to update the data to UI&period; LiveData only updates app component observers that are in an active lifecycle state&period;<&sol;p> &NewLine;<p><strong><span style&equals;"color&colon; &num;0000ff&semi;">MainViewModel&period;kt<&sol;span><&sol;strong><&sol;p>&NewLine;<&excl;-- WP QUADS Content Ad Plugin v&period; 2&period;0&period;98&period;1 -->&NewLine;<div class&equals;"quads-location quads-ad2" id&equals;"quads-ad2" style&equals;"float&colon;none&semi;margin&colon;0px&semi;">&NewLine;&NewLine;<&sol;div>&NewLine; &NewLine;<pre>import androidx&period;lifecycle&period;MutableLiveData<br &sol;>import androidx&period;lifecycle&period;ViewModel<br &sol;>import com&period;c1ctech&period;mvvmwithnetworksource&period;Movie<br &sol;>import com&period;c1ctech&period;mvvmwithnetworksource&period;model&period;MovieList<br &sol;>import com&period;c1ctech&period;mvvmwithnetworksource&period;repository&period;MainRepository<br &sol;>import retrofit2&period;Call<br &sol;>import retrofit2&period;Callback<br &sol;>import retrofit2&period;Response<br &sol;><br &sol;>class MainViewModel&lpar;private val repository&colon; MainRepository&rpar; &colon; ViewModel&lpar;&rpar; &lbrace;<br &sol;><br &sol;> val movieList &equals; MutableLiveData&lt&semi;List&lt&semi;Movie&gt&semi;&gt&semi;&lpar;&rpar;<br &sol;> val errorMessage &equals; MutableLiveData&lt&semi;String&gt&semi;&lpar;&rpar;<br &sol;><br &sol;> fun getAllMovies&lpar;&rpar; &lbrace;<br &sol;> val response &equals; repository&period;getAllMovies&lpar;&rpar;<br &sol;> response&period;enqueue&lpar;object &colon; Callback&lt&semi;MovieList&gt&semi; &lbrace;<br &sol;> override fun onResponse&lpar;call&colon; Call&lt&semi;MovieList&gt&semi;&comma; response&colon; Response&lt&semi;MovieList&gt&semi;&rpar; &lbrace;<br &sol;> movieList&period;postValue&lpar;response&period;body&lpar;&rpar;&quest;&period;mList&rpar;<br &sol;> &rcub;<br &sol;><br &sol;> override fun onFailure&lpar;call&colon; Call&lt&semi;MovieList&gt&semi;&comma; t&colon; Throwable&rpar; &lbrace;<br &sol;> errorMessage&period;postValue&lpar;t&period;message&rpar;<br &sol;> &rcub;<br &sol;> &rcub;&rpar;<br &sol;> &rcub;<br &sol;>&rcub;<&sol;pre> &NewLine;<h4><span style&equals;"color&colon; &num;000080&semi;"><strong>ViewModel Factory<&sol;strong><&sol;span><&sol;h4> &NewLine;<p>To create ViewModel we have <strong><span style&equals;"color&colon; &num;008000&semi;">ViewModelProviders<&sol;span><&sol;strong> utility provided by Android&period; But ViewModelProviders can only instantiate ViewModels with the no-arg constructor&period;<br &sol;>So to create a ViewModel with multiple arguments&comma; we need to use a Factory that we can pass to ViewModelProviders to use when an instance of MyViewModel is required&period;<&sol;p> &NewLine;<p><strong><span style&equals;"color&colon; &num;0000ff&semi;">MyViewModelFactory&period;kt<&sol;span><&sol;strong><&sol;p> &NewLine;<pre>import androidx&period;lifecycle&period;ViewModel<br &sol;>import androidx&period;lifecycle&period;ViewModelProvider<br &sol;>import com&period;c1ctech&period;mvvmwithnetworksource&period;repository&period;MainRepository<br &sol;>import com&period;c1ctech&period;mvvmwithnetworksource&period;viewmodel&period;MainViewModel<br &sol;><br &sol;>class MyViewModelFactory constructor&lpar;private val repository&colon; MainRepository&rpar; &colon;<br &sol;> ViewModelProvider&period;Factory &lbrace;<br &sol;> override fun &lt&semi;T &colon; ViewModel&quest;&gt&semi; create&lpar;modelClass&colon; Class&lt&semi;T&gt&semi;&rpar;&colon; T &lbrace;<br &sol;> return if &lpar;modelClass&period;isAssignableFrom&lpar;MainViewModel&colon;&colon;class&period;java&rpar;&rpar; &lbrace;<br &sol;> MainViewModel&lpar;this&period;repository&rpar; as T<br &sol;> &rcub; else &lbrace;<br &sol;> throw IllegalArgumentException&lpar;"ViewModel Not Found"&rpar;<br &sol;> &rcub;<br &sol;> &rcub;<br &sol;>&rcub;<&sol;pre> &NewLine;<h4><strong><span style&equals;"color&colon; &num;000080&semi;">Setting up the UI<&sol;span><&sol;strong><&sol;h4> &NewLine;<p>In the UI part&comma; We need to create an instance of the ViewModel and observe the API response&period; Based on the API response we need to update the UI&period;<&sol;p> &NewLine;<h5><strong><span style&equals;"color&colon; &num;0000ff&semi;">Creating Activity Layout file<&sol;span><&sol;strong><&sol;h5> &NewLine;<p>The below layout file contains a RecyclerView&period;<&sol;p> &NewLine;<p><strong><span style&equals;"color&colon; &num;0000ff&semi;">activity&lowbar;main&period;xml<&sol;span><&sol;strong><&sol;p> &NewLine;<pre>&lt&semi;&quest;xml version&equals;"1&period;0" encoding&equals;"utf-8"&quest;&gt&semi;<br &sol;>&lt&semi;androidx&period;constraintlayout&period;widget&period;ConstraintLayout xmlns&colon;android&equals;"http&colon;&sol;&sol;schemas&period;android&period;com&sol;apk&sol;res&sol;android"<br &sol;> xmlns&colon;app&equals;"http&colon;&sol;&sol;schemas&period;android&period;com&sol;apk&sol;res-auto"<br &sol;> xmlns&colon;tools&equals;"http&colon;&sol;&sol;schemas&period;android&period;com&sol;tools"<br &sol;> android&colon;layout&lowbar;width&equals;"match&lowbar;parent"<br &sol;> android&colon;layout&lowbar;height&equals;"match&lowbar;parent"<br &sol;> tools&colon;context&equals;"&period;MainActivity"&gt&semi;<br &sol;><br &sol;> &lt&semi;androidx&period;recyclerview&period;widget&period;RecyclerView<br &sol;> android&colon;id&equals;"&commat;&plus;id&sol;recyclerview"<br &sol;> android&colon;layout&lowbar;width&equals;"match&lowbar;parent"<br &sol;> android&colon;layout&lowbar;height&equals;"wrap&lowbar;content"<br &sol;> app&colon;layoutManager&equals;"androidx&period;recyclerview&period;widget&period;LinearLayoutManager"<br &sol;> app&colon;layout&lowbar;constraintEnd&lowbar;toEndOf&equals;"parent"<br &sol;> app&colon;layout&lowbar;constraintStart&lowbar;toStartOf&equals;"parent"<br &sol;> app&colon;layout&lowbar;constraintTop&lowbar;toTopOf&equals;"parent"<br &sol;> tools&colon;itemCount&equals;"5"<br &sol;> tools&colon;listitem&equals;"&commat;layout&sol;layout&lowbar;rv&lowbar;item" &sol;&gt&semi;<br &sol;><br &sol;>&lt&semi;&sol;androidx&period;constraintlayout&period;widget&period;ConstraintLayout&gt&semi;<&sol;pre> &NewLine;<h5><strong><span style&equals;"color&colon; &num;0000ff&semi;">Creating Adapter Layout file<&sol;span><&sol;strong><&sol;h5> &NewLine;<p>The below layout file represents the UI of each item of recyclerView&period;<&sol;p> &NewLine;<p><strong><span style&equals;"color&colon; &num;0000ff&semi;">layout&lowbar;rv&lowbar;item&period;xml<&sol;span><&sol;strong><&sol;p> &NewLine;<pre>&lt&semi;&quest;xml version&equals;"1&period;0" encoding&equals;"utf-8"&quest;&gt&semi;<br &sol;>&lt&semi;androidx&period;cardview&period;widget&period;CardView xmlns&colon;android&equals;"http&colon;&sol;&sol;schemas&period;android&period;com&sol;apk&sol;res&sol;android"<br &sol;> xmlns&colon;app&equals;"http&colon;&sol;&sol;schemas&period;android&period;com&sol;apk&sol;res-auto"<br &sol;> android&colon;layout&lowbar;width&equals;"match&lowbar;parent"<br &sol;> android&colon;layout&lowbar;height&equals;"wrap&lowbar;content"<br &sol;> android&colon;layout&lowbar;margin&equals;"8dp"<br &sol;> android&colon;elevation&equals;"8dp"<br &sol;> app&colon;cardCornerRadius&equals;"8dp"&gt&semi;<br &sol;><br &sol;> &lt&semi;ImageView<br &sol;> android&colon;id&equals;"&commat;&plus;id&sol;moviePoster"<br &sol;> android&colon;layout&lowbar;width&equals;"match&lowbar;parent"<br &sol;> android&colon;layout&lowbar;height&equals;"200dp"<br &sol;> android&colon;scaleType&equals;"fitCenter" &sol;&gt&semi;<br &sol;><br &sol;> &lt&semi;TextView<br &sol;> android&colon;id&equals;"&commat;&plus;id&sol;movieTitle"<br &sol;> android&colon;layout&lowbar;width&equals;"match&lowbar;parent"<br &sol;> android&colon;layout&lowbar;height&equals;"wrap&lowbar;content"<br &sol;> android&colon;background&equals;"&commat;color&sol;purple&lowbar;700"<br &sol;> android&colon;gravity&equals;"center&lowbar;vertical"<br &sol;> android&colon;padding&equals;"3dp"<br &sol;> android&colon;textAppearance&equals;"&commat;style&sol;TextAppearance&period;AppCompat&period;Large"<br &sol;> android&colon;textColor&equals;"&commat;android&colon;color&sol;white" &sol;&gt&semi;<br &sol;><br &sol;>&lt&semi;&sol;androidx&period;cardview&period;widget&period;CardView&gt&semi;<&sol;pre> &NewLine;<h5><strong><span style&equals;"color&colon; &num;0000ff&semi;">Creating Adapter class<&sol;span><&sol;strong><&sol;h5> &NewLine;<p>The MainAdapter is an adapter class for the recycler view to set all the items into recycler view&period;<&sol;p> &NewLine;<p><strong><span style&equals;"color&colon; &num;0000ff&semi;">MainAdapter&period;kt<&sol;span><&sol;strong><&sol;p> &NewLine;<pre>import android&period;view&period;LayoutInflater<br &sol;>import android&period;view&period;ViewGroup<br &sol;>import androidx&period;recyclerview&period;widget&period;RecyclerView<br &sol;>import com&period;bumptech&period;glide&period;Glide<br &sol;>import com&period;c1ctech&period;mvvmwithnetworksource&period;databinding&period;LayoutRvItemBinding<br &sol;><br &sol;>class MainAdapter &colon; RecyclerView&period;Adapter&lt&semi;MainViewHolder&gt&semi;&lpar;&rpar; &lbrace;<br &sol;><br &sol;> var movies &equals; mutableListOf&lt&semi;Movie&gt&semi;&lpar;&rpar;<br &sol;><br &sol;> fun setMovieList&lpar;movies&colon; List&lt&semi;Movie&gt&semi;&rpar; &lbrace;<br &sol;> this&period;movies &equals; movies&period;toMutableList&lpar;&rpar;<br &sol;> notifyDataSetChanged&lpar;&rpar;<br &sol;> &rcub;<br &sol;><br &sol;> override fun onCreateViewHolder&lpar;parent&colon; ViewGroup&comma; viewType&colon; Int&rpar;&colon; MainViewHolder &lbrace;<br &sol;> val inflater &equals; LayoutInflater&period;from&lpar;parent&period;context&rpar;<br &sol;><br &sol;> val binding &equals; LayoutRvItemBinding&period;inflate&lpar;inflater&comma; parent&comma; false&rpar;<br &sol;> return MainViewHolder&lpar;binding&rpar;<br &sol;> &rcub;<br &sol;><br &sol;> override fun onBindViewHolder&lpar;holder&colon; MainViewHolder&comma; position&colon; Int&rpar; &lbrace;<br &sol;> val movie &equals; movies&lbrack;position&rsqb;<br &sol;> holder&period;binding&period;movieTitle&period;text &equals; movie&period;title<br &sol;> Glide&period;with&lpar;holder&period;itemView&period;context&rpar;&period;load&lpar;movie&period;poster&rpar;&period;placeholder&lpar;R&period;drawable&period;placeholder&rpar;<br &sol;> &period;into&lpar;holder&period;binding&period;moviePoster&rpar;<br &sol;><br &sol;> &rcub;<br &sol;><br &sol;> override fun getItemCount&lpar;&rpar;&colon; Int &lbrace;<br &sol;> return movies&period;size<br &sol;> &rcub;<br &sol;>&rcub;<br &sol;><br &sol;>class MainViewHolder&lpar;val binding&colon; LayoutRvItemBinding&rpar; &colon; RecyclerView&period;ViewHolder&lpar;binding&period;root&rpar; &lbrace;&rcub;<&sol;pre> &NewLine;<h5><strong><span style&equals;"color&colon; &num;0000ff&semi;">Creating MainActivity File<&sol;span><&sol;strong><&sol;h5> &NewLine;<p>Inside MainActivity&comma; we will observe the response from the API and update the UI&period;<&sol;p> &NewLine;<p><span style&equals;"color&colon; &num;0000ff&semi;"><strong>MainActivity&period;kt<&sol;strong><&sol;span><&sol;p> &NewLine;<pre>import androidx&period;appcompat&period;app&period;AppCompatActivity<br &sol;>import android&period;os&period;Bundle<br &sol;>import android&period;util&period;Log<br &sol;>import androidx&period;lifecycle&period;Observer<br &sol;>import androidx&period;lifecycle&period;ViewModelProvider<br &sol;>import com&period;c1ctech&period;mvvmwithnetworksource&period;databinding&period;ActivityMainBinding<br &sol;>import com&period;c1ctech&period;mvvmwithnetworksource&period;repository&period;MainRepository<br &sol;>import com&period;c1ctech&period;mvvmwithnetworksource&period;viewmodel&period;MainViewModel<br &sol;><br &sol;>class MainActivity &colon; AppCompatActivity&lpar;&rpar; &lbrace;<br &sol;> private val TAG &equals; "MainActivity"<br &sol;> private lateinit var binding&colon; ActivityMainBinding<br &sol;><br &sol;> lateinit var viewModel&colon; MainViewModel<br &sol;><br &sol;> private val retrofitService &equals; RetrofitService&period;getInstance&lpar;&rpar;<br &sol;> val adapter &equals; MainAdapter&lpar;&rpar;<br &sol;><br &sol;> override fun onCreate&lpar;savedInstanceState&colon; Bundle&quest;&rpar; &lbrace;<br &sol;> super&period;onCreate&lpar;savedInstanceState&rpar;<br &sol;> binding &equals; ActivityMainBinding&period;inflate&lpar;layoutInflater&rpar;<br &sol;> setContentView&lpar;binding&period;root&rpar;<br &sol;><br &sol;><strong><span style&equals;"color&colon; &num;008000&semi;"> &sol;&sol;get viewmodel instance using MyViewModelFactory<&sol;span><&sol;strong><br &sol;> viewModel &equals;<br &sol;> ViewModelProvider&lpar;this&comma; MyViewModelFactory&lpar;MainRepository&lpar;retrofitService&rpar;&rpar;&rpar;&period;get&lpar;<br &sol;> MainViewModel&colon;&colon;class&period;java<br &sol;> &rpar;<br &sol;><br &sol;><strong><span style&equals;"color&colon; &num;008000&semi;"> &sol;&sol;set recyclerview adapter<&sol;span><&sol;strong><br &sol;> binding&period;recyclerview&period;adapter &equals; adapter<br &sol;><br &sol;> viewModel&period;movieList&period;observe&lpar;this&comma; Observer &lbrace;<br &sol;> Log&period;d&lpar;TAG&comma; "movieList&colon; &dollar;it"&rpar;<br &sol;> adapter&period;setMovieList&lpar;it&rpar;<br &sol;> &rcub;&rpar;<br &sol;><br &sol;> viewModel&period;errorMessage&period;observe&lpar;this&comma; Observer &lbrace;<br &sol;> Log&period;d&lpar;TAG&comma; "errorMessage&colon; &dollar;it"&rpar;<br &sol;> &rcub;&rpar;<br &sol;><br &sol;> viewModel&period;getAllMovies&lpar;&rpar;<br &sol;> &rcub;<br &sol;>&rcub;<&sol;pre> &NewLine;<p>When you run the app it will look like this&colon;<&sol;p> &NewLine;<p><img class&equals;"alignnone wp-image-3112" src&equals;"https&colon;&sol;&sol;c1ctech&period;com&sol;wp-content&sol;uploads&sol;2022&sol;02&sol;Screenshot&lowbar;20220221-161915&lowbar;MVVMWithNetworkSource-498x1024&period;jpg" alt&equals;"" width&equals;"362" height&equals;"745" &sol;><&sol;p> &NewLine;<p>&nbsp&semi;<&sol;p> &NewLine;&NewLine;

Exit mobile version