ダイエット中の植物コントローラー:Android

MVCパターンはかなり前に登場し、アプリケーションのビジネスロジックをプレゼンテーションから分離するために作成されました。 しかし、すべてのプログラマーがそれを正しく実装しているわけではありません。そのため、大量のコードを含む「厚くumbいいコントローラー」があります。 この記事では、コントローラー内のコード量を削減し、アプリケーションの純粋なビジネスロジックの余地を残すために、Viewクラスの適切な実装について説明します。







MVCにはアクティブモデルとパッシブモデルの2つのタイプがあり、パッシブモデルは単純なデータソース(データベースのDAOなど)として機能し、アクティブモデル自体がサブスクライバーのステータスを更新するという違いがあります。 -ビュー。 パッシブモデルはより普遍的でシンプルであり、さらに、開発で最もよく使用されるため、この記事では例として使用します。 彼女の図を見てみましょう。







ユーザーはコントローラーと対話し、コントローラーはモデルにデータを要求し、ユーザーに表示されるビューに入力します。すべてがシンプルです。





コントローラーとモデルですべてが明らかであるように見える場合、Viewではいくつかの困難がありますが、主な理由はViewです。何もないため、コントローラーが表示用のデータを送信できるインターフェースを持つ個別のViewクラスを作成することを考えていません。 最も単純にxmlマークアップを作成し、コントローラーに直接入力します。そのため、理論上はビジネスロジックを含むはずのコードに、テキストの色、フォントサイズ、TextViewでのテキストの設定、ActionBar、NavigatonDrawerの操作などの表示詳細が入力されます「オームなど。 その結果、アクティビティコードは1000行になり、一見すると何らかの種類のゴミが含まれています。



別のViewクラスを作成せずに典型的なAndroidアプリケーションを作成する方法と、Viewを完全に使用する別の方法を見てみましょう。



このアプリケーションは、ユーザープロファイルを読み込んで表示するという非常に一般的なタスクを解決します。 実装を始めましょう。



これを行うには、ユーザーの名前と姓を格納するモデルクラスUserを作成します。



public class User { private final String firstname; private final String lastname; public User(String firstname, String lastname) { this.firstname = firstname; this.lastname = lastname; } // getters }
      
      





そして、それを「ロード」するプロバイダークラス。 このクラスはデモンストレーション用に作成されました。実際のプロジェクトでは、AsyncTaskを使用してデータをロードしたり、アクティビティライフサイクルを考慮したり、エラーを処理したりしない独自の自転車を作成したりしないでください。 ここでは、ほとんどの場合、このクラスが必要です。これは、データを別のストリームにロードする実装の詳細を隠すためだけです。



 public class UserProvider { //    Callback public void loadUser(Callback callback) { new LoadUserTask(callback).execute(); } public class LoadUserTask extends AsyncTask<Void, Void, User> { private Callback callback; public LoadUserTask(Callback callback) { this.callback = callback; } @Override protected User doInBackground(Void... params) { User user = new User("firstname", "lastname"); return user; } @Override protected void onPostExecute(User user) { super.onPostExecute(user); callback.onUserLoaded(user); } } public interface Callback { void onUserLoaded(User user); } }
      
      





次に、xmlレイアウトが作成されます。これは省略され、コントローラーはビューとモデルを接続し、アプリケーションにビジネスロジックを導入する必要があります。 アクティビティはコントローラーとして機能し、通常は次のように実装されます。



 public class UserProfileActivity extends Activity implements Callback { private TextView firstnameTxt, lastnameTxt; private ProgressBar progressBar; private UserProvider userProvider; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_user_profile); firstnameTxt = (TextView) findViewById(R.id.firstname); lastnameTxt = (TextView) findViewById(R.id.lastname); progressBar = (Progressbar) findViewById(R.id.progressBar); userProvider = new UserProvider(); loadUser(); } @Override public void onUserLoaded(User user) { hideProgressBar(); showUser(user); } private void loadUser() { showProgressBar(); userProvider.loadUser(this); } public void showUser(User user) { firstnameTxt.setText(user.getFirstname()); lastnameTxt.setText(user.getLastname()); } public void showProgressBar() { progressBar.setVisibility(View.VISIBLE); } public void hideProgressBar() { progressBar.setVisibility(View.INVISIBLE); } }
      
      





画面が開くと、プロファイルの読み込みが開始され、進行状況バーが表示されます。プロファイルが読み込まれると、進行状況バーが非表示になり、画面にデータが表示されます。

このコードからわかるように、作業とプレゼンテーションおよびビジネスロジックが混在しています。

すべてがそれほど悪くないように見える場合、プロジェクトの開発により、そのようなコードは読みにくくなり、保守が困難になります。



OOPについて考え、コードに抽象化を加えましょう。



 public class UserView { private final TextView firstnameTxt, lastnameTxt; private final ProgressBar progressBar; public UserView(View rootView) { firstnameTxt = (TextView) rootView.findViewById(R.id.firstname); lastnameTxt = (TextView) rootView.findViewById(R.id.lastname); progressBar = (ProgressBar) rootView.findViewById(R.id.progressBar); } public void showUser(User user) { firstnameTxt.setText(user.getFirstname()); lastnameTxt.setText(user.getLastname()); } public void showProgressBar() { progressBar.setVisibility(View.VISIBLE); } public void hideProgressBar() { progressBar.setVisibility(View.INVISIBLE); } }
      
      





ビューは、アクティビティビューですべての作業を行います。 ユーザープロファイルを表示するには、showUser(User)メソッドを使用してモデルオブジェクトを渡すだけです。 Viewの実際のプロジェクトでは、showProgressBar()、hideProgressBar()などの補助メソッドを転送できる基本クラスを作成することが望ましいです。 その結果、ビューを操作するすべてのロジックがアクティビティから独立したエンティティに取り込まれ、コントローラーコードの量が大幅に削減され、ビューを操作する透過的な抽象化が作成されます。



アクティビティは、TextViewやその他のコントロールについて何も知りません。 ビューとのすべての対話は、UserViewクラスとそのインターフェイスを使用して行われます。



 public class UserProfileActivity extends Activity { private UserView userView; private UserProvider userProvider; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_user); userView = new UserView(getWindow().getDecorView()) userProvider = new UserProvider(); loadUser(); } @Override public void onUserLoaded(User user) { userView.hideProgressBar(); userView.showUser(user); } private void loadUser() { userView.showProgressBar(); userProvider.loadUser(this); } }
      
      





これで、コントローラーはUserViewとUserProviderの2つのエンティティのみで動作するようになり、データ表示を実装する複雑さがなくなりました。 コードはよりわかりやすく、わかりやすくなりました。



現在、UserViewクラスはデータを表示するだけです。画面を切り替える間で状態を保存したい場合があります。この問題は、View状態をParcelableまたはBundleに書き込むメソッドを作成することで簡単に解決できます。 また、ほとんどの場合、クリックを処理する機能が必要になります。この場合、OnClickListener自体はViewクラスで作成し、コントローラーが実装するCallbackをそのクラスに渡す方が適切です。



実際、それがすべてです。 これにより、Androidで過小評価されているビューの問題が解決されます。 このアプローチを使用すると、コントローラー内のコードの量が著しく減少し、抽象化のレベルが増加し、ドルが再び30ルーブルかかります。



また読む:

iOSアプリのスタイル設定:フォント、色、画像のストレッチ方法

モバイルアプリケーションのアーキテクチャ設計

モバイルアプリケーションのアーキテクチャ設計:パート2



All Articles