# Android Architecture: MVC Pattern ###### tags: `Android Architecture` [TOC] ## What is MVC? ![](https://i.imgur.com/zBO4t2k.png =500x350) MVC stands for Model-View-Controller. ### Each part **Model:** It is the data layer, responsible for managing the business logic and handling network or database API. **View:** It is the UI showing the data obtained from model. **Controller:** Gets the information from model and updates the View. ### How it works? 1. The View calls the Controller to handle the view. 2. Controller seeks Model to get information. 3. Model Will get the information from API and returns it back to Controller. 4. Controller will handle the view. ## MVC Coding Parts ### 1. Model #### Information Main Structure: ```java== import com.google.gson.annotations.SerializedName; public class Country { @SerializedName("name") public String countryName; @SerializedName("capital") public String capitalName; @SerializedName("region") public String regionName; } ``` #### Interface used in >Why is it ++*@GET("all")*++? That is because the url was: https://restcountries.eu/rest/v2/++**all**++[color=red] ``` java== public interface CountriesApi { @GET("all") Single<List<Country>> getCountries(); } ``` #### Retrieve information from API: CountriesService Class used Retrofit library to get information from the API. ``` java== public class CountriesService { public static final String BASE_URL = "https://restcountries.eu/rest/v2/"; private CountriesApi api; public CountriesService() { Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); api = retrofit.create(CountriesApi.class); } public Single<List<Country>> getCountries(){ return api.getCountries(); } } ``` ### 2. View In this case, view will be the MVCActivity. You will notice that you will have to instantiate a Controller here in order to use it. >**Note:** Controller in this case is called MVCController and it is instantiated in onCreate() and also used in onRetry() method.[color=pink] >**Notice:** Context is given to the controller to know which view it is linked to. Here we will understand that both view and controller are ++strongly linked++.[color=red] ``` java== public class MVCActivity extends AppCompatActivity{ private RecyclerView rv_country; private MVCAdapter mvcAdapter; private MVCController mvcController; private Button btn_retry; private ProgressBar pb_bar; public interface onClickI{ public void onClick(int i); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_mvc); setTitle("MVC"); this.rv_country = findViewById(R.id.rv_country); this.btn_retry = findViewById(R.id.btn_retry); this.pb_bar = findViewById(R.id.pb_bar); this.mvcAdapter = new MVCAdapter(new onClickI() { @Override public void onClick(int i) { Toast.makeText(MVCActivity.this, "" + i, Toast.LENGTH_SHORT).show(); } }); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); this.rv_country.setAdapter(mvcAdapter); this.rv_country.setLayoutManager(layoutManager); mvcController = new MVCController(this); } public void setValues(ArrayList<Country> countryList){ this.mvcAdapter.setCountryList(countryList); this.btn_retry.setVisibility(View.GONE); this.pb_bar.setVisibility(View.GONE); this.rv_country.setVisibility(View.VISIBLE); } public static Intent getIntent(Context context){ return new Intent(context, MVCActivity.class); } public void onRetry(View view){ mvcController.onRetry(); this.btn_retry.setVisibility(View.GONE); this.pb_bar.setVisibility(View.VISIBLE); this.rv_country.setVisibility(View.GONE); } public void onError(){ Toast.makeText(this, R.string.error_msg, Toast.LENGTH_SHORT).show(); this.btn_retry.setVisibility(View.VISIBLE); this.pb_bar.setVisibility(View.GONE); this.rv_country.setVisibility(View.GONE); } } ``` ### 3. Controller In the controller we will have an instance of the view that Controller is taking care of. That is why controller also depends a lot on the view. On the other hand, it gets information from the Model which is in this case the CountriesService. After the information is obtained it will set it back to the view. >**Note:** Inside Controller we will write what changes and actions we will do to the view, when some functions/tasks are done. [color=pink] > >**For example:** (See example below) When we do controller.onRetry() in our view, we will call fetchCountries() and by the end we call view.methodName() like view.setValues(), where we change the recyclerview.[color=pink] ``` java== import java.util.ArrayList; import java.util.List; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.observers.DisposableSingleObserver; import io.reactivex.schedulers.Schedulers; import studio.zc.androidarchitecture.model.CountriesService; import studio.zc.androidarchitecture.model.Country; public class MVCController { private MVCActivity view; private CountriesService service; public MVCController(MVCActivity view) { this.view = view; service = new CountriesService(); fetchCountries(); } public void fetchCountries(){ service.getCountries() .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableSingleObserver<List<Country>>() { @Override public void onSuccess(List<Country> value) { ArrayList<Country> rv_list = new ArrayList<>(); rv_list.addAll(value); view.setValues(rv_list); } @Override public void onError(Throwable e) { view.onError(); } }); } public void onRetry(){ fetchCountries(); } } ``` ## Advantage & Disadvantages **Advantage:** * Easy to order in comparison to writing all in onCreate(). **Disadvantage:** * The View and Controller are heavily linked mutually. Because both have instances of each other. * Low flexibility due to link. Controller cannot change view. * 1 View corresponds to 1 Controller (1 to 1). If there are too many views, then there will be same amount of controllers.