Androidのアプリケーションアーキテクチャの進化

入門

以前アーキテクチャについてモバイル端末APPの話から考えられ、特にアンドロイドの蓄積の終わりには、モバイル開発の長年の経験をまとめたもので、実際には、少しはこれ以上、大きなほとんどのプロジェクトは、ビジネスの根拠を行っているので、バナーを開催していない、と多くの場合ではありません複雑なデータ処理や高い並行性(のみ個人的な目的のために);アーキテクチャおよび長い単語が大規模システムやWebで使用されていることを保持少し良く、良い良いアーキテクチャを終了、システムをよりロバストな、高い効率を意味し、より大きな体重ました。要するに、やり過ぎ感のようなものが、しかし、Androidのアプリケーション開発の規模の拡大と、クライアント側のビジネスロジックより複雑ではなく、単純なデータは既に示し、APPはまたアーキテクチャ、および分割ビューのデータである必要があり、重合度を改善するためのモジュール、内部モジュールとの間の結合を解除します。

APPのプログラム構造

プロジェクトレベルの点では、開発者のためにプロジェクト全体を構築し、モジュール、Androidの一般的なプログラム構造を分割する方法を決定します。

  • UIレイヤ
    データの表示と管理
    ユーザーとの対話を
    描画する
    アダプタを

  • Yewuluojiceng
    (グローバルデータに対応するメモリ、)永続的なデータ
    のデータ暗号化式(データ層は、必要なデータがUI層に加工する必要が時々ある)
    データ変更通知機構

  • データ層の
    データアクセス(DB、ファイル、ネットワークなど)の
    キャッシュ(写真、文書など)
    の設定ファイル(共有perference)

プログラム構造から、アーキテクチャはAPPにどこにでもある、しかし我々は、最も単純な事実についてあまり心配していない、関与デモアーキテクチャ(通常はMVC)です。アーキテクチャを考えるように変更されているが、現状、アンドロイドから創業以来、モバイル端末のアーキテクチャは、最初のMVCからMVPに、(モバイル端末にRNにより導入された)不人気フラッターからGoogleのAAC / MVVMに、何度も変更しましたキャッチ。それはターンMVC、MVP、MVVMで主流のアーキテクチャ設計のこれらのタイプを紹介します、そこにコードのアーキテクチャ上の非常に詳細な分析の間に違いはありません、しかし、適切なインフラの選択を容易にするために、プロジェクトで自分のデザインのアイデアを分析すること。

MVC

非常に古典的なアーキテクチャ、そのようなアーキテクチャを持っているプラ​​ットフォームに関係なく、使いやすく、手頃な価格。Androidのは、Java、この開発モデルは、実際にMVCのアイデアを採用しており、ビューとコントローラ分離により活動におけるビジネスロジックを開発し、ページレイアウトを実現するためにXMLファイルを使用しています。モデル(モデル)、ビュー(ビュー)とコントローラ(コントローラ):モードMVC(モデル - ビュー - コントローラ)ソフトウェアエンジニアリングは、ソフトウェア・アーキテクチャ・モデルで、ソフトウェアは、3つの基本的な部分に分割されます。

ウィキペディア:
MVCモデルはまず、トリグヴェReenskaugによって1978年に提案されたプログラミング言語Smalltalkの発明として、1980年代にゼロックスのパロアルト研究所(XeroxPARC)のソフトウェアアーキテクチャです。その後の修正および簡略化の手順の拡張、及びプログラムの一部の再利用が可能となるようにMVCパターンオブジェクトは、動的プログラミングを達成することです。このモードでは、より直感的なプログラム構造の複雑さを簡素化することもできます。同時に、それぞれの基本的な部分の基本的な部分を分離することにより、ソフトウェアシステム自体も、適切な機能を提供します。専門家は、彼らの専門知識によってグループ化することができます。

  • コントローラ(コントローラ) - 要求を処理するための要求を転送する責任。
  • ビュー(ビュー) - インタフェースデザイナーグラフィカルなインターフェイスのデザイン。
  • モデル(モデル) - プログラマはプログラムが機能するはず書くため(アルゴリズムなど)、データベース専門家のデータ管理とデータベース設計(特定の機能を実現することができます)。

XMLに対応するAndroidのプログラミング、表示レイアウトファイル、ソリッドモデル(ネットワーク、データベース、I / O)に対応するモデルでは、コントローラのアクティビティは、ビジネスロジック、データ処理及びUI処理に対応します。下図のように:

Androidのアプリケーションアーキテクチャの進化

//Model
public interface WeatherModel {
    void getWeather(String cityNumber, OnWeatherListener listener);
}
................

public class WeatherModelImpl implements WeatherModel {
    @Override
    public void getWeather(String cityNumber, final OnWeatherListener listener) {
        /*数据层操作*/
        VolleyRequest.newInstance().newGsonRequest(http://www.weather.com.cn/data/sk/ + cityNumber + .html,
        Weather.class, new Response.Listener<weather>() {
            @Override
            public void onResponse(Weather weather) {
                if (weather != null) {
                    listener.onSuccess(weather);
                } else {
                    listener.onError();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                listener.onError();
            }
        });
    }
}

//Controllor(View)层
public class MainActivity extends ActionBarActivity implements OnWeatherListener, View.OnClickListener {
    private WeatherModel weatherModel;
    private EditText cityNOInput;
    private TextView city;
    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        weatherModel = new WeatherModelImpl();
        initView();
    }

    //初始化View
    private void initView() {
        cityNOInput = findView(R.id.et_city_no);
        city = findView(R.id.tv_city);
        ...
        findView(R.id.btn_go).setOnClickListener(this);
    }

    //显示结果
    public void displayResult(Weather weather) {
        WeatherInfo weatherInfo = weather.getWeatherinfo();
        city.setText(weatherInfo.getCity());
        ...
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_go:
                weatherModel.getWeather(cityNOInput.getText().toString().trim(), this);
                break;
        }
    }

    @Override
    public void onSuccess(Weather weather) {
        displayResult(weather);
    }

    @Override
    public void onError() {
        Toast.makeText(this, 获取天气信息失败, Toast.LENGTH_SHORT).show();
    }

    private T findView(int id) {
        return (T) findViewById(id);
    }
}

分析の例:

  • コントロール内の活動はどのように自分のショーを知るためには、サービスやデータを気にしなければなりません。
  • 内部活動のすべてのロジック。

したがって、実際の開発プロセスにおいて、純粋に個々のXMLファイルビュー機能が弱いように、アクティビティビューとコントローラは、基本的に適合され、ディスプレイを表示するために必要であり、また、制御ロジックを追加する責任があり、多くは、コードの量で得られた、機能を引き受けます素晴らしいです。現在のすべての従来の開発は、それらのほとんどは、活動を通じて調整され、ビュー・モデル・モードを言うことがより適切でなければなりません。

MVP

MVPには3つの部分から構成MVC、MVPアーキテクチャからの移行である:表示するためのビューが担当する、論理処理を担当するプレゼンターは、モデルデータを提供しました。MVCからMVPにAndroidの開発者の遷移は、最も重要な変更はプレゼンターに、ビジネス・ロジック・コードの責任活動で、活動はビューのMVP、プレゼンターとのインタフェースを制御するインタフェースを初期化し、確立する責任団体として機能します。

たとえば、MVC、ページもう少し複雑、かつ千個のアクティビティコードよりも多くのビジネスロジックは非常に簡単ですが、それは標準のMVC活動モード・コントローラではないが、その主な責任は、アプリケーションのレイアウトとユーザーの初期化をロードすることですインターフェース、およびユーザから受信及び処理動作要求、したがって応答します。それは肥大化になるようにインターフェイスと継続的な改善、成長している責任のActivityクラスのそのロジックの複雑さと、分割を考えるのが自然です。この分割後、プレゼンターは肥大化アクティビティを回避する、論理演算の多数を行いました。以下に示すように、全体の構造:

Androidのアプリケーションアーキテクチャの進化

//Model层
/**
 * 定义业务接口
 */
public interface IUserBiz {
    public void login(String username, String password, OnLoginListener loginListener);
}

/**
 * 结果回调接口
 */
public interface OnLoginListener {
    void loginSuccess(User user);

    void loginFailed();
}

/**
 * 具体Model的实现
 */
public class UserBiz implements IUserBiz {
    @Override
    public void login(final String username, final String password, final OnLoginListener loginListener) {
        //模拟子线程耗时操作
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //模拟登录成功
                if ("zhy".equals(username) && "123".equals(password)) {
                    User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);
                    loginListener.loginSuccess(user);
                } else {
                    loginListener.loginFailed();
                }
            }
        }.start();
    }
}

//View
public interface IUserLoginView {
    String getUserName();

    String getPassword();

    void clearUserName();

    void clearPassword();

    void showLoading();

    void hideLoading();

    void toMainActivity(User user);

    void showFailedError();
}

//然后Activity实现这个这个接口:
public class UserLoginActivity extends ActionBarActivity implements IUserLoginView {
    private EditText mEtUsername, mEtPassword;
    private Button mBtnLogin, mBtnClear;
    private ProgressBar mPbLoading;
    private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_login);
        initViews();
    }

    private void initViews() {
        mEtUsername = (EditText) findViewById(R.id.id_et_username);
        mEtPassword = (EditText) findViewById(R.id.id_et_password);
        mBtnClear = (Button) findViewById(R.id.id_btn_clear);
        mBtnLogin = (Button) findViewById(R.id.id_btn_login);
        mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading);
        mBtnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mUserLoginPresenter.login();
            }
        });
        mBtnClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mUserLoginPresenter.clear();
            }
        });
    }

    @Override
    public String getUserName() {
        return mEtUsername.getText().toString();
    }

    @Override
    public String getPassword() {
        return mEtPassword.getText().toString();
    }

    @Override
    public void clearUserName() {
        mEtUsername.setText("");
    }

    @Override
    public void clearPassword() {
        mEtPassword.setText("");
    }

    @Override
    public void showLoading() {
        mPbLoading.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {
        mPbLoading.setVisibility(View.GONE);
    }

    @Override
    public void toMainActivity(User user) {
        Toast.makeText(this, user.getUsername() +
                " login success , to MainActivity", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showFailedError() {
        Toast.makeText(this,
                "login failed", Toast.LENGTH_SHORT).show();
    }
}

//Presenter
public class UserLoginPresenter {
    private IUserBiz userBiz;
    private IUserLoginView userLoginView;
    private Handler mHandler = new Handler();

    //Presenter必须要能拿到View和Model的实现类
    public UserLoginPresenter(IUserLoginView userLoginView) {
        this.userLoginView = userLoginView;
        this.userBiz = new UserBiz();
    }

    public void login() {
        userLoginView.showLoading();
        userBiz.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() {
            @Override
            public void loginSuccess(final User user) {
                //需要在UI线程执行
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        userLoginView.toMainActivity(user);
                        userLoginView.hideLoading();
                    }
                });
            }

            @Override
            public void loginFailed() {
                //需要在UI线程执行
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        userLoginView.showFailedError();
                        userLoginView.hideLoading();
                    }
                });
            }
        });
    }

    public void clear() {
        userLoginView.clearUserName();
        userLoginView.clearPassword();
    }
}

説明:

  • プレゼンターでのやり方へのコールバックデータによるモデル。
  • ビュー(活性)メソッドプレゼンタによって要求されたデータが露出し、ユーザ操作に応答する責任があります。
  • データを取得した後、プレゼンターは、ビュー(活性)の方法によって達成インタフェース制御モデルは、ネットワーク、およびデータベースI / Oなどを含む、モデルによってデータを得るために、露出しています。

MVP明らかな利点を使用すると、従来の開発の場合を回避することであるとモデルビューモード結合は、コードの利便性は、アセンブリ多重化機能、効率、およびチームワークユニットテストを拡張することができる改善されます。しかし、また、のようないくつかの欠点があります。

  • プレゼンターモデルデータ転送プロセスは、コールバックを必要とします。
  • ビュー(活性)、また、制御の複雑さを増加させる、参照プレゼンタービュー(活性)を保持する必要が同時に参照プレゼンターを保持する必要があります。
  • MVCコードでの活動は、MVPでプレゼンターに転送し、非常に肥大化され、また、プレゼンターコードを発生させた際に、複雑なビジネスロジック肥大化しました。

だから、MVPのMVCは、単にそれが結合を低減するために界面層の追加である、と述べました。

MVVM

MVVM 架构模式是微软在 2005 年诞生的,MVVM是Model-View-ViewModel的简称,它由三个部分组成,也就是 Model、View 和 ViewModel,其中视图模型(ViewModel)其实就是 PM 模式中的展示模型,在 MVVM 中叫做视图模型。从实际效果来看,ViewModel是View的数据模型和Presenter的结合,具体结构如下图所示:

Androidのアプリケーションアーキテクチャの進化

说明:

  • Model(模型层)通过网络和本地数据库获取视图层所需数据;
  • View(视图层)采用XML文件进行界面的描述;
  • ViewModel(视图-模型层)负责View和Model之间的通信,以此分离视图和数据。

View和Model之间通过Android Data Binding技术,实现视图和数据的双向绑定;ViewModel持有Model的引用,通过Model的方法请求数据;获取数据后,通过Callback(回调)的方式回到ViewModel中,由于ViewModel与View的双向绑定,使得界面得以实时更新。同时,界面输入的数据变化时,由于双向绑定技术,ViewModel中的数据得以实时更新,提高了数据采集的效率。

MVVM架构将Presenter改名为ViewModel,基本上与MVP模式完全一致,唯一的区别是,它采用双向绑定(data-binding)View的变动,自动反映在 ViewModel,反之亦然,这就导致了我们如果要完整的采用 MVVM 必须熟练的掌握 DataBinding 等基础组建,这就给我们MVVM引入项目带了困难。

总结

実際には、MVC、MVPとMVVMが絶対的に良いか悪いかではなく、ソフトウェアのプログラミングでは、これらのパターンのメリットを比較し、実際のプロジェクトでは無意味であるから、様々なモードは、長所と短所を持って、良いか悪いか何が存在しない、どちらか一方を必要としませんでしたポイント。実装するために、より高度なアーキテクチャより複雑で、より多くのマンパワーを必要とする技術選択キーは、独自のプロジェクト、チームのレベル、資源の特性の開発時間を制限しているように、これらは、学ぶために多くのコスト焦点を当てます!しかし、MVVMの前にカートを置く多くのチームは、厳格に自分のプロジェクトに適用されます。最も重要なことは、ソフトウェア保守性と拡張性の高い凝集、低カップリングを、できるようにすることです。

建築的思考が携帯端末「MVX」として理解することができ、それはこのルールに従った分業を言うことです、我々はハードだと思うし、問題狭く階層アーキテクチャを検討する必要はありませんし、モデル - ビュー - Xは(することができ、もちろん、あなたも自分自身を追加することができます続きますいくつかの補助モジュール層)。

おすすめ

転載: blog.51cto.com/14332859/2425931