みなさまこんにちは〜!
メモリアインクのすだです。
本日は、
Androidアプリ開発における「MVP」と呼ばれるアーキテクチャの基本について、実際のコードを用いて解説していきます!
この記事を読んでわかること…
・MVPというアーキテクチャについて
・MVPでの実装方法
環境
- Kotlin (ver 1.9.0)
 - Android Studio (Giraffe | 2022.3.1 Patch 3)
 
MVPとは?
MVP(Model-View-Presenter)は、Androidアプリ開発においてよく使われるアーキテクチャパターンのひとつです。
「画面表示のロジック」と「データの処理ロジック」を明確に分けることで、
保守性やテストのしやすさが向上します。
MVPの3つの役割
①Model(モデル)
アプリ内のデータ処理やビジネスロジックを担当します。たとえばAPI通信やDB操作など。
②View(ビュー)
ユーザーインターフェース(UI)部分。ActivityやFragmentがこれにあたります。
③Presenter(プレゼンター)
ModelとViewの橋渡し役。ユーザーの操作に応じて、Modelに命令を出し、結果をViewに渡します。


なぜMVPが必要なのか?MVCとの比較
まず前提として、「アーキテクチャの目的」は各役割の「責任」を明確に分けることです。
これによって、バグが起きにくくなる、修正がしやすくなる、テストがしやすくなるといったメリットがあります。
比較1:View(画面表示部分)の責務
・MVCでは、ActivityやFragmentがViewとControllerの両方の役割を持ちがちです。
そのため、「UIの表示」も「イベントの処理」も「データ取得」も全部ここに書かれてしまい、肥大化(Fat Activity)になりがちです。
(AndroidではControllerが明確に存在しないため、結局ActivityやFragmentがViewとControllerを兼ねることが多い)
・一方MVPでは、ActivityやFragmentは表示だけに集中。
たとえば「ボタンが押されたらどうするか?」というロジックは、Presenterが担当します。
【MVC】
    [Activity]  ⇄  [Model]
       ↑ ↓
     View + Controller混在
     
【MVP】
    [View(Activity)]
        ↓↑
     [Presenter]
        ↓↑
      [Model]比較2:テストのしやすさ
・MVCでは、UIのコードにロジックが混ざっているため、
テストを書くにはUIも再現する必要がある=手間が多い&壊れやすい。
・MVPでは、Presenterがロジックだけを持っていて、Viewとの通信はインターフェース(interface)経由。
このため、テスト時にはモック(仮のView)を使ってテストができます。
比較3:Androidとの親和性
Androidでは、公式に「Controller」という概念が明確に提供されていないため、MVCをそのまま使うのは実は少し難しいです。
MVPは「Presenter」という中間役を自分で作れるので自由度が高く、Androidに合わせやすいのです。
MVPやMVVMが「UIの構造に関する設計パターン」であるのに対し、
クリーンアーキテクチャは「アプリ全体の依存関係と責務分離のための原則」ということになります。
MVVMやクリーンアーキテクチャの設計については以下の記事で詳細を説明しておりますので、ぜひ合わせてご覧ください!↓




サンプル処理で学ぶMVP実装(Kotlin)
それでは、MVPアーキテクチャを採用して「画面にあるボタンを押下するとメッセージがトースト表示される」という簡単な処理を作ってみます。
図でまとめると以下のような流れになるようにします。
[ MainActivity (View) ]
        ↑     ↓
     show / click
        ↑     ↓
[ MainPresenterImpl ]
        ↑     ↓
    getMessage()
        ↑     ↓
[ MessageModelImpl (Model) ]前提理解①:
インターフェース(interface)とは?
「何ができるか(振る舞い・機能)」を約束するだけの設計図です。
中身(実装)は書かず、どんな関数を持つべきかだけを定義します。
前提理解②:
クラス(class)とは?
具体的な設計と中身(処理)が入った部品です。
変数や関数を持ち、実際の振る舞いやデータを定義できます。
View
インターフェイスの実装
// Viewに期待する操作を定義する「契約」インターフェース
interface MainView {
    fun showMessage(message: String)
}Activityの実装
class MainActivity : AppCompatActivity(), MainView {
    private lateinit var presenter: MainPresenter
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // Presenterに自分(View)とModelの実装を注入
        presenter = MainPresenterImpl(this, MessageModelImpl())
        findViewById<Button>(R.id.button).setOnClickListener {
            presenter.onButtonClick()
        }
    }
    // ViewがUIを表示する処理
    override fun showMessage(message: String) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
    }
}↑ここでユーザーのアクションをクリックリスナーで検知し、ボタン押下後の処理をPresenterに委ねます。
Presenter
インターフェイスの実装
interface MainPresenter {
    fun onButtonClick()
}Presenterの実装
// Presenterの中身(ロジック)を実装
class MainPresenterImpl(
    private val view: MainView,
    private val model: MessageModel
) : MainPresenter {
    override fun onButtonClick() {
        val message = model.getMessage()
        view.showMessage(message)
    }
}↑ここでPresenterは、UIからのイベント通知(ボタンクリック)を受け取ってModelを通して必要なデータを取得し、
それをViewに渡してUI表示を更新させるという一連の処理を担います。
Model
インターフェイスの実装
// データの取得や処理を定義
interface MessageModel {
    fun getMessage(): String
}Modelの実装
// 実際のデータ処理の中身
class MessageModelImpl : MessageModel {
    override fun getMessage(): String {
        return "こんにちは!"
    }
}↑今回はただ文字列を返しているだけですが、他にも以下のような処理を行います。
・Web APIとの通信(Retrofitなど)
・データベースの読み書き(Roomなど)
・ファイルアクセス
・データ加工や整形
・キャッシュ処理 など
まとめ
おつかれさまでした。いかがでしたでしょうか!
たとえ小さなアプリでも、MVPの考え方を取り入れておくことで、後の機能追加や保守がとても楽になります。
まずはこのサンプルのようなシンプルな構成から始め、徐々に応用してみてくださいね!
技術者としてのキャリアパスを次のレベルへと進めたい皆様、
<未経験からIT・Webエンジニアを目指すなら【ユニゾンキャリア】>![]()
![]()
自分の市場価値をさらに向上させてみませんか?
それではまた次回の記事でお会いしましょう!


			







コメント