Mobile Development 12 min read

Understanding MVC, MVP, and MVVM in Android with a Three‑in‑One Demo

This tutorial walks through Android implementations of MVC, MVP (using Mosby), and MVVM (with DataBinding), providing concise explanations, annotated code snippets, and a unified demo that lets beginners quickly grasp the differences and start building each architectural pattern in just ten minutes.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Understanding MVC, MVP, and MVVM in Android with a Three‑in‑One Demo

The article introduces three common Android architectural patterns—MVC, MVP, and MVVM—by presenting a simple click‑button demo that simulates a time‑consuming task, updates a TextView, and demonstrates how each pattern structures the same functionality.

MVC : The Activity acts as both Controller and part of the View, directly invoking a Model class to perform background work. Key code:

public class MvcMainActivity extends AppCompatActivity {
    TextView greetingTextView;
    Button helloButton;
    Button goodbyeButtonClicked;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvcmain);
        greetingTextView = findViewById(R.id.greetingTextView);
        helloButton = findViewById(R.id.helloButton);
        goodbyeButtonClicked = findViewById(R.id.goodbyeButtonClicked);
        helloButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new GreetingGeneratorModel("HelloWorld", greetingTextView).execute();
            }
        });
        goodbyeButtonClicked.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new GreetingGeneratorModel("GoodBye", greetingTextView).execute();
            }
        });
    }
}

public class GreetingGeneratorModel extends AsyncTask
{
    private String baseText;
    private TextView greetingTextView;
    public GreetingGeneratorModel(String baseText, TextView greetingTextView) {
        this.baseText = baseText;
        this.greetingTextView = greetingTextView;
    }
    @Override
    protected Integer doInBackground(Void... params) {
        Thread.sleep(2000);
        return (int) (Math.random() * 100);
    }
    @Override
    protected void onPostExecute(Integer randomInt) {
        if ("HelloWorld".equals(baseText)) {
            greetingTextView.setTextColor(Color.RED);
        } else {
            greetingTextView.setTextColor(Color.BLUE);
        }
        greetingTextView.setText(baseText + randomInt);
    }
}

MVP : Uses the Mosby library. The View interface (HelloWorldView) defines UI actions, the Presenter handles business logic, and the Model remains similar but reports results via a callback. Key snippets:

public interface HelloWorldView extends MvpView {
    void showHello(String greetingText);
    void showGoodbye(String greetingText);
}

public class MvpMainActivity extends MvpActivity
implements HelloWorldView {
    // UI fields omitted for brevity
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvpmain);
        // find views …
        helloButton.setOnClickListener(v -> presenter.greetHello());
        goodbyeButtonClicked.setOnClickListener(v -> presenter.greetGoodbye());
    }
    @Override
    public void showHello(String greetingText) {
        greetingTextView.setTextColor(Color.RED);
        greetingTextView.setText(greetingText);
    }
    @Override
    public void showGoodbye(String greetingText) {
        greetingTextView.setTextColor(Color.BLUE);
        greetingTextView.setText(greetingText);
    }
    @Override
    public HelloWorldPresenter createPresenter() {
        return new HelloWorldPresenter();
    }
}

public class HelloWorldPresenter extends MvpBasePresenter
{
    private GreetingGeneratorModel greetingTask;
    public void greetHello() {
        cancelTask();
        greetingTask = new GreetingGeneratorModel("HelloWorld", (text) -> {
            if (isViewAttached()) getView().showHello(text);
        });
        greetingTask.execute();
    }
    public void greetGoodbye() {
        cancelTask();
        greetingTask = new GreetingGeneratorModel("GoodBye", (text) -> {
            if (isViewAttached()) getView().showGoodbye(text);
        });
        greetingTask.execute();
    }
    // cancelTask() and detachView() omitted for brevity
}

MVVM : Relies on Android DataBinding. The layout file starts with a <layout> tag containing <data> that declares a handler object and a data object. The Activity binds these objects, eliminating explicit click listeners. Key snippets:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="handlers" type="com.example.architecturalpatterndemo.mvvm.MyHandlers" />
        <variable name="greetingGeneratorObj" type="com.example.architecturalpatterndemo.mvvm.GreetingGeneratorObj" />
    </data>
    <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
        <TextView android:id="@+id/greetingTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{greetingGeneratorObj.baseText}" />
        <Button android:id="@+id/helloButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{handlers.onClickHello}" android:text="hello" />
        <Button android:id="@+id/goodbyeButtonClicked" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{handlers.onClickGoodbye}" android:text="Good bye" />
    </LinearLayout>
</layout>
public class MvvmMainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMvvmmainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_mvvmmain);
        GreetingGeneratorObj obj = new GreetingGeneratorObj("");
        binding.setGreetingGeneratorObj(obj);
        binding.setHandlers(new MyHandlers(obj));
    }
}

public class MyHandlers {
    private GreetingGeneratorObj greetingGeneratorObj;
    public MyHandlers(GreetingGeneratorObj obj) { this.greetingGeneratorObj = obj; }
    public void onClickHello(View view) {
        new GreetingGeneratorModel("HelloWorld", greetingGeneratorObj).execute();
    }
    public void onClickGoodbye(View view) {
        new GreetingGeneratorModel("GoodBye", greetingGeneratorObj).execute();
    }
}

The article concludes with a link to the full demo repository (https://github.com/youjinjin/ArchitecturalPatternDemo) and invites readers to explore related Android topics.

mobile developmentarchitectureAndroidMVCMVVMMVPDataBinding
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.