Android是否支持MVC(模型视图控制器)结构?

时间:2012-08-27 09:34:51

标签: android model-view-controller

我想知道,如果Android支持MVC(模型视图控制器)结构?如果有支持的话 1.什么是控制器? 2.什么是模特?和 3.什么是观点?

请清除我。我对此有些困惑。

5 个答案:

答案 0 :(得分:22)

Which design patterns are used on Android?

  

模型 - 视图 - 控制工作正常

     

实际的Activity类不会扩展android的View类,但它   但是,它会处理向用户显示窗口并处理   该窗口的事件(onCreateonPause等)。

     

这意味着,当您使用 MVC模式时,您的控制器   实际上将是伪视图控制器。既然是处理   使用附加视图组件向用户显示窗口   您已使用setContentView添加到其中,并且还处理了事件   至少各种活动生命周期事件。

     

在MVC中,控制器应该是主要入口点。哪一个   如果在将它应用于android时就是这种情况,那就有点争议了   发展,因为activity是大多数人的自然切入点   应用

所以,Android中的伪MVC:

模型 =具有主要业务逻辑的实体或类

查看 =布局,资源和小部件,例如EditText

控制器 = ActivityAdaptor

enter image description here

答案 1 :(得分:5)

模型 =内容提供商。

控制器 =活动,片段或服务。

查看 = XML布局。

答案 2 :(得分:3)

MVC已经在Android中实现

View =布局,资源和内置类,如从android.view.View派生的Button。

Controller =活动和片段

Model =实现应用程序逻辑的类

答案 3 :(得分:0)

实施MVC模式的主要目标是,这样做可以让您以后“退出”。他们中的任何一个并且在没有对其他两个人进行必要的改变的情况下拍了一个新的。

模型:关于数据的所有内容。什么是操纵,存储什么以及如何操作。

查看:所有关于用户界面或演示文稿。显示的内容和方式。

控制器:事件处理程序。指示其他两个是为了响应事件而运行的。

在Android中,MVC的这种实现具有扩展Activity类的类形式的控制器。毕竟,这个班级最初收到的是“'事件”。构成Android Activity的生命周期(即onStart(),onCreate(),onSuspend(),onStop(),onResume(),onDestroy)。随着Android的发展,这个生命周期可能会发生变化,因此将其表示为MVC模式的Controller组件是有意义的。

再次,通过这个MVC实现,我可以提取三个组件中的任何一个,并基本上放入一个全新的接口(View),或一个全新的数据库(Model),或一个新的Activity生命周期(Controller)没有改变其他两个。唯一必要的是每个组件都遵循下面列出的样板模板。

在此实现中,三个MVC组件分别由三个java类表示:appView.java,appController.java,appModel.java

在查看每个类时,请记下成员变量,mController,mAppView和mAppModel,并查看每个java文件中引用它们的方式和时间。 这些成员变量是钩子'允许每个组件互相引用。

此外,您还会注意到mAppModel会进一步分解,并使用另一个名为dbHelper的类。这可以让你分开什么'数据是从'如何'数据被操纵和存储。

public class appController extends Activity {

    appView mAppView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mAppView = new appView(this);

        mAppView.onCreate(savedInstanceState);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        return mAppView.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        boolean result;

        switch (item.getItemId()) {
            case ....

                return true;

            case ....


                return true;

            default:

                result = mAppView.onOptionsItemSelected(item);
        }

        if ( !result )
            result = super.onOptionsItemSelected(item);

        return result;
    }


    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {

        mAppView.onCreateContextMenu(menu, v, menuInfo);
    }


    @Override
    public boolean onContextItemSelected(MenuItem item) {

        return mAppView.onContextItemSelected(item);
    }

    // When a startActivityForResult() is called
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        mAppView.onActivityResult(requestCode, resultCode, data);
    }


    @Override
    protected void onStop(){
        super.onStop();

        mAppView.onStop();
    }

    @Override
    protected void onRestart(){
        super.onRestart();

        mAppView.onRestart();
    }

    @Override
    protected void onDestroy(){
          super.onDestroy();

          mAppView.onDestroy();

          mAppView = null;
    }

控制器appController实现了大部分' Activity生命周期' mehtods然后在视图中调用appView方法。这意味着标准生命周期方法onStop,onResume,onDestroy等不仅在Controller中实现,而且还在此MVC模式的View部分中实现。您稍后会看到Model部分也是如此。

您可以在View实现中看到,appView,成员变量mController,用于访问Activity方法,但允许将Activity(Controller)与UI分离(布局,菜单等)

public class appView {


    private Activity mController;

    private Context mContext;

    private appModel mAppModel;


    public appView(Activity activity) {
        this((Context) activity);

        mController = activity;
    }

    // This can be called when there is not activity available.
    public appView(Context context){

        mContext = context;

        mAppModel = new appModel(this);
    }

    protected void onCreate(Bundle savedInstanceState) {

        mController.setContentView(R.layout.whatever_you_want_activity);

        btnNewToDo = (Button) mController.findViewById(.....

        // The New button.
        btnNewToDo.setOnClickListener(......

        lvToDos = (ListView) mController.findViewById(......

        // One click will edit that selected item.
        lvToDos.setOnItemClickListener(........
    }

    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater inflater = mController.getMenuInflater();

        inflater.inflate(R.menu.whatever_you_want_menu, menu);

        return true;
    }


    public boolean onOptionsItemSelected(MenuItem item) {

       ....
    }


    protected void onStop(){

        mAppModel.onStop();
    }

    protected void onRestart(){

        mAppModel.onRestart();
    }

    protected void onDestroy() {

        mController = null;

        mContext = null;

        if(mAppModel != null ){

            mAppModel.onDestroy();

            mAppModel = null;
        }
    }
}

该模型如下所列。 查看此类如何在视图和控制器的构造函数中。控制器被视为Context类型而不是Activity。这允许您涉及Context类型的任何对象,而不一定是Activity对象。

此外,您将在构造函数中看到一个辅助类dbHelper。

public class appModel {

    private appView mAppView;
    private Context mContext;

    // Holds the database helper
    private dbHelper mDBHelper;


    public appModel(appView appView){

        mAppView = appView;

        mContext = mAppView.getContext();

        mDBHelper = new dbHelper(mContext);
    }


    public boolean open() {

        if (mDBHelper == null) return false;

        return mDBHelper.open().isOpen();
    }


    public void close(){

        mDBHelper.close();
    }

    // The App might get destroyed with calling onDestroy, and so close it.
    protected void onStop(){

        // close the db connection...
        close();
    }

    protected void onRestart() {

        // db likely closed.
        open();
    }

    protected void onDestroy(){

        mAppView = null;

        mContext = null;

        mDBHelper.onDestroy();

        mDBHelper = null;
    }
}

如下所示,SQLite是此应用程序中使用的数据库。但是,切换出这个助手类dbHelper,你可以使用一个完全不同的数据库,而其他组件则不是更明智的。

下面是一些基本方法(开放,关闭等),让您了解此处执行的功能。此外,请注意onDestroy()方法在此处关闭数据库连接。它由上面的视图调用,当控制器被销毁时,控制器会调用它。

这个助手类知道数据库中字段的名称。 通过这种实现,视图,控制器甚至模型都不需要坦率地知道所使用的数据库类型甚至是字段名称。

public class dbHelper extends SQLiteOpenHelper {

    private SQLiteDatabase mDB;

    private Context mContext;


    static final String DATABASE_NAME = "whatever";

    static final String DATABASE_FILE = DATABASE_NAME + ".db";

    static final String DBKEY_FIELD = "rowid";

    static final int DATABASE_VERSION = 5;

    // SQL Statement to create a new database.
    private static final String DATABASE_CREATE = "CREATE TABLE IF NOT EXISTS " + DATABASE_NAME
            + "(....  );";

    // SQL statement used to upgrade the database.
    private final String ALTER_TABLE = "ALTER TABLE " + DATABASE_NAME + " ADD COLUMN anewfield VARCHAR;";

    private final String SELECT_ALL = "SELECT " + DBKEY_FIELD + " AS _id, * FROM " + DATABASE_NAME + " ORDER BY somefield ASC";

    private static final String DROP_TABLE = "DROP TABLE IF EXISTS " + DATABASE_NAME;


    public dbHelper(Context controller) {
        super(controller, DATABASE_FILE, null, DATABASE_VERSION);

        mContext = controller;
    }

    // Called when no database exists or if there is a new 'version' indicated.
    @Override
    public void onCreate(SQLiteDatabase db) {

        db.execSQL(DATABASE_CREATE);
    }


    public dbHelper open() {

        try {

            mDB = getWritableDatabase();

        } catch (SQLException ex) {

            if (mDB != null && mDB.isOpen()) {

                mDB.close();
            }

            if (mDB != null) {

                mDB = null;
            }
        }

        return this;
    }


    public boolean isOpen() {

        return mDB != null && mDB.isOpen();
    }


    public void close() {
        super.close();

        // It's good to lose the reference here with the connection closed.
        mDB = null;
    }


    protected void onDestroy() {

        close();

        // Just making sure.
        mDB = null;

        mContext = null;
    }


    public SQLiteDatabase getDatabaseInstance() {

        return mDB;
    }



    private Cursor runQuery(String sqlStmt) {

        Cursor records;

        try {

            records = mDB.rawQuery(sqlStmt, null);

        } catch (RuntimeException ex) {

            // If something goes wrong, return an empty cursor.
            records = new MatrixCursor(new String[]{"empty"});
        }

        return records;
    }


    protected boolean dropTable() {

        boolean dropped;

        try {

            mDB.execSQL("DROP TABLE IF EXISTS " + DATABASE_NAME);

            dropped = true;

        } catch (SQLException ex) {

            dropped = false;
        }

        return dropped;
    }


    @Override
    public void onConfigure(SQLiteDatabase db) {
    }

    @Override
    public void onOpen(SQLiteDatabase db) {
    }

    // Called when the database needs to be upgraded to the current version.
@Override
    public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion) {

        if ( _oldVersion >= _newVersion){

            Log.w(mContext.getClass().getSimpleName(), "Cannot 'upgrade' from version " + _newVersion + " to " + _oldVersion + ". Upgrade attempt failed.");
        }

        try {

            _db.execSQL(ALTER_TABLE);

        }catch(RuntimeException ex){

            Log.e(mContext.getClass().getSimpleName(), "Database upgrade failed. Version " + _oldVersion + " to " + _newVersion);

            throw ex;
        }

        // Log the version upgrade.
        Log.i(mContext.getClass().getSimpleName(), "Database upgrade. Version " + _oldVersion + " to " + _newVersion);
    }

}

答案 4 :(得分:0)

不是真正的MVC,而是通过Room和LiveData

变得更加MVC

在经典MVC中,控制器是关于决策制定的,下一步要采取行动。该视图从模型中读取数据并更新它自己的字段。

在Android活动中,他们同时执行这两项操作,他们决定在回答事件时要执行的操作,并设置布局的字段。他们还从模型中读取数据并连接小部件。这些活动结合了两者的逻辑任务,即经典控制器和经典视图。

这就是为什么在大多数情况下我不会谈论MVC。控制器和视图之间没有清晰的分离。 Java代码和XML资源之间存在清晰的分离。这是有道理的,因为在更大的团队中,不同的人负责视觉布局和编程。

您仍然可以编写自己的视图组件,并将这部分代码作为视图来处理。它只是经典视图的钝化部分,而逻辑在活动和片段中加入了控制器。我不会谈论视图,而是谈论组件或小部件。智能小部件越多,它们再次占据经典视图的逻辑就越多。

另一方面,如果您应用像Room这样的库,Android会再次成为MVC。 Room和LiveData使视图能够一直观察模型中的变化,直至数据库中的变化。如果您干净地分离视图内容并将控制器减少到决策制定,您可以通过某种方式构建您的体系结构,它确实值得再次命名为MVC。

底线

这取决于开发者。可以将真正的MVC应用到Android,但它不是默认情况。