Android架构设计之MVC模式

一、MVC基本概念

MVC(Model-View-Controller,模型-视图-控制器)模式在Android中曾经是比较流行的架构设计模式;使用MVC设计模式的好处UI界面与业务逻辑数据的分离,在修改或者优化界面及用户交互的同时,无需重新编写业务逻辑。Android中的MVC的角色如下:

  • 模型层(Model):是用进行业务逻辑的处理,比如一些网络访问操作、数据库的操作等等,总之一些耗时操作的任务。
  • 视图图(View):主要是处理数据显示的部分,在Android中xml布局就可以视为V层。
  • 控制层(Controller):在Android中,Activity是处理用户交互问题,因此通常把Activity或者Fragment视为控制器,通过C层来操作M层获取数据,并把数据返回给V层显示

二、MVC基本使用

项目目录结构分成了三个目录,分别是model、controller、listener,其中model目录下存放一些javabean类和业务数据获取接口及其实现类(网络访问);controller目录存放Activity或者Fragment;listener目录下是存放网络访问操作结果的回调接口,目的是将数据返回给View层显示。下面一个简单登录为例:
这里写图片描述

LoginListener接口:其实这个接口实现回调也相当于model层中一部分。

/**
 * desc:登录回调监听
 */

public interface LoginListener<T> {

    /*请求前一些准备,比如加载提示等待*/
    void onStart_();

    /*访问成功调用*/
    void onSuccess(T t);

    /*访问失败*/
    void onFailed();

    /*访问结束*/
    void onFinish();

}

Model层:

/**
 * desc: 用户信息实体类
 */

public class UserInfo {

    private String userName;

    private String sex;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}
/**
 * desc: login-Model
 */

public interface LoginModel<T>{

    void getUserInfo(String userName, String pwd, LoginListener<T> listener);
}
/**
 * desc:LoginModel的实现类,网络异步访问
 */

public class LoginModelImpl implements LoginModel<UserInfo>{

    @Override
    public void getUserInfo(String userName, String pwd, LoginListener<UserInfo> listener) {

        UserInfo userInfo = new UserInfo();
        userInfo.setUserName(userName);
        //下面是模拟网络访问结果的调用
        listener.onStart_();
        if (!TextUtils.isEmpty(userName) && !TextUtils.isEmpty(pwd)){
            listener.onSuccess(userInfo);
        }else {
            listener.onFailed();
        }
        listener.onFinish();

    }


}

View层:xml布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <EditText
        android:id="@+id/et_user_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"/>

    <EditText
        android:id="@+id/et_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPassword"/>

    <Button
        android:id="@+id/but_login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="登录"/>
</LinearLayout>

Controller层:

public class MainActivity extends AppCompatActivity implements LoginListener<UserInfo> {

    private EditText mEtName;
    private EditText mEtPassword;
    private Button mButLogin;
    private LoginModelImpl mLoginModel;
    private ProgressDialog mProgressDialog;

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

        mEtName = findViewById(R.id.et_user_name);
        mEtPassword = findViewById(R.id.et_password);
        mButLogin = findViewById(R.id.but_login);
        mLoginModel=new LoginModelImpl();
        mButLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //登录
                String userName = mEtName.getText().toString();
                String pwd = mEtPassword.getText().toString();
                mLoginModel.getUserInfo(userName,pwd,MainActivity.this);
            }
        });

    }

    @Override
    public void onStart_() {
        Log.d(TAG, "onStart_: ");
        mProgressDialog=new ProgressDialog(this);
        mProgressDialog.setTitle("请求中……");
        mProgressDialog.show();
    }

    @Override
    public void onSuccess(UserInfo userInfo) {
        Log.d(TAG, "onSuccess: ");
        mProgressDialog.dismiss();
        Toast.makeText(this,"登录成功",Toast.LENGTH_SHORT).show();
    }


    @Override
    public void onFailed() {
        Log.d(TAG, "onFailed: ");
        Toast.makeText(this,"登录失败",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onFinish() {
        Log.d(TAG, "onFinish: ");
        mProgressDialog.dismiss();
    }

    private static final String TAG = "MainActivity";
}

上面例子是MVC的简单运用,当你点击登录就是获取登录数据,通过modle层中的接口实现类(LoginModelImpl)来获取网络数据,并把数据返回View层显示交互,从上面例子可以看出,Controller控制器Activity一定程度上实现了视图UI层与数据Modle层的解耦,将View层和Modle
层进行了分离,但并不是十分完美,就是在Controller层Activity中同时存在布局视图初始化和业务逻辑操作响应,也就是View层初始化和Controller层同时绑定到同一类中。当业务越来越复杂时,Activity的职责会越来越多,代码会越来越浮肿,不利于后期的维护。

Android架构设计之MVP模式

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用android studio 运行,下面是一个简单的文档,这个代码是一个demo 一、Activity的使用 1、SNActivity 框架最基本的activity,可调用$(SNManager)进行操作activity,具体用法请参考文档或代码 2、SNNavigationSlidingActivity 包含SNActivity的功能,继承于com.jeremyfeinstein.slidingmenu.lib.app.SlidingActivity 支持导航条和左滑视图的Activity 加载导航条: loadNavBar(int height,int background_color_id) loadNavBarResId(int height_id,int background_id) 加载左侧视图: /** * load left view * @param left_id left layout id * @param offset_value offset value * @param shadow_width_value shadow width value * @param shadow_drawable_id shadow drawable style * @param fade fade value */ loadLeft(int left_id, int offset_value, int shadow_width_value, int shadow_drawable_id, float fade) /** * load left view * @param left_id left layout id * @param offset_id offset id * @param shadow_width_id shadow width id * @param shadow_drawable_id shadow drawable id * @param fade fade value */ loadLeftResId(int left_id, int offset_id, int shadow_width_id, int shadow_drawable_id, float fade) 二、SNElement的使用 View的伪装对象,支持所有View的功能,详细功能可参考文档或代码 手动伪装:$.create $.id $.findView 注入伪装:$.setContent(view class or layout id,inject class); 获取原型:elem.toView(); 三、注入 1、视图注入 A、创建注入类,属性名称必须和layout的id对应,如果不对应请加入标签@SNInjectView class DemoInject{ @SNInjectView(id=R.id.tvTest) public SNElement test; } B、实例化注入对象 DemoInject di=new DemoInject(); C、调用$.inject或者$.setContent注入 $.inject(di); D、注入成功后即可调用对象 String text=di.test.text(); 2、依赖注入 A、需要绑定注入对象,建议写到Application的onCreate SNBindInjectManager.instance().bind(ITest.class, Test.class); B、与视图注入不同的是属性必须添加标签@SNIOC,注入的对象(Test)必须包含只有一个SNManager参数的构造函数,且必须实现注入者 public class Test implements ITest{ SNManager $; public Test(SNManager _$){ this.$=_$; }; } class DemoInject{ @SNIOC public ITest test; } C、调用$.inject或者$.setContent注入 同视图注入 D、注入成功后即可调用对象 di.test.xxx(); 四、fragment的使用 1、SNFragment 2、SNLazyFragment 五、控件的使用 1、SNFragmentScrollable 2、SNPercentLinearLayout、SNPercentRelativeLayout 3、SNScrollable 4、SNSlipNavigation 5、XList 6、slidingtab

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值