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

Posted

技术标签:

【中文标题】Android 是不是支持 MVC(模型视图控制器)结构?【英文标题】:Does Android supports MVC (Model View Controller) Structure?Android 是否支持 MVC(模型视图控制器)结构? 【发布时间】:2012-08-21 19:01:40 【问题描述】:

我想知道,如果android支持MVC(模型视图控制器)结构?如果支持那么 1. 什么是控制器? 2.什么是型号?和 3. 什么是视图?

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

【问题讨论】:

***.com/questions/2925054/mvc-pattern-in-android 的可能重复项 从这里开始查看我的博文Android Architecture: MV? 【参考方案1】:

不是真正的 MVC,而是通过 Room 和 LiveData 变得更加 MVC

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

在 Android 活动中,两者都做,它们决定运行什么动作来响应事件,并设置布局的字段。他们还从模型中读取数据并连接小部件。这些活动结合了经典控制器和经典视图两者的逻辑任务。

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

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

另一方面,如果您应用 Room 之类的库,Android 将再次变得更加 MVC。 Room 和 LiveData 使视图能够观察模型的变化,一直到数据库的变化。如果您清楚地分离视图内容并将控制器简化为决策制定,那么您可以以某种方式构建您的架构,它确实再次配得上 MVC 的名称。

底线

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

【讨论】:

【参考方案2】:

实现 MVC 模式的主要目标是,这样做之后您可以“拉出”其中的任何一个并添加一个新的,而无需对其他两个进行很少或没有必要的更改。

模型:所有关于数据。操作了什么,存储了什么以及如何操作。

视图:所有关于 UI 或演示的信息。显示什么以及如何显示。

控制器:事件处理程序。指示其他两个响应事件何时运行。

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

同样,通过这个 MVC 实现,我可以取出三个组件中的任何一个,然后放入一个全新的界面(视图)、一个全新的数据库(模型)或一个新的活动生命周期(控制器)其他两个没有变化。唯一需要的是每个组件都尊重下面列出的样板模板。

在这个实现中,三个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 实现了大部分“活动生命周期”方法,并依次调用视图 appView 中的方法。这意味着标准的生命周期方法,onStop、onResume、onDestroy 等不仅在 Controller 中实现,而且在此 MVC 模式的 View 部分中实现。稍后您会看到模型部分也是如此。

您可以在下面的 View 实现中看到 appView,其成员变量 mController 用于访问 Activity 方法,但允许将 Activity(控制器)与 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() 方法在这里关闭数据库连接。它由上面的 View 调用,当它被销毁时又由 Controller 调用。

正是这个帮助类知道数据库中字段的名称。 有了这个实现,视图、控制器甚至模型都不需要知道所使用的数据库类型甚至字段名称。

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);
    


【讨论】:

【参考方案3】:

Which design patterns are used on Android?

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

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

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

在 MVC 中,控制器应该是主入口点。哪一个 如果将其应用于android时是这种情况,则有点值得商榷 开发,因为activity 是大多数人的自然切入点 应用程序。

所以,android 中的伪 MVC:

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

视图 = 布局、资源和小部件,例如EditText

控制器 = Activity , Adaptor

【讨论】:

酷!但是这些片段在这个架构中去哪里了? 我完全同意你的看法!【参考方案4】:

模型 = 内容提供者。

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

视图 = XML 布局。

【讨论】:

【参考方案5】:

MVC 已经在 Android 中实现了

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

控制器 = 活动和片段

Model = 实现应用逻辑的类

【讨论】:

以上是关于Android 是不是支持 MVC(模型视图控制器)结构?的主要内容,如果未能解决你的问题,请参考以下文章

Android开发之MVC设计模式

Android——基础

Android框架模式之MVC与MVP

Android入门:MVC模式(中)

MVC 中的模型到视图通信?

什么是 MVC(模型视图控制器)? [关闭]