Android中Mvc框架实现方式

在MVP大行其道的当下,很多的产品都在使用MVP作为主流的框架实现方式。一方面MVP实现的完全的解耦,另一方面MVP也可以在一些情况下共用接口。不过这里我给大家提供一种MVC的框架。这种框架的好处是,我们可以更加简洁的完成代码解耦,简单易行。在项目比较简单的时候我们可以使用这种方法。当然,这种方法在大型项目中表现也是一流的。

首先我先分析一下我们的类结构。

第一个自然是布局文件,这个这里就不再多提了。

第二个就是Activity或者Fragment了。这里我们提供了基类的写法。之前我在

Android框架入门,基类的写法(一)--------  BaseActivity

系类文章中已经提到过相关的写法,这里就是对这个基类的一种重新封装。

先上BaseActivity写法

/**
 * Activity基类
 * Created by WaterWood on 2018/5/9.
 */
public abstract class BaseActivity<T extends MvcBaseModel> extends AppCompatActivity {

    protected T mModel;
    //日志打印标志
    protected String TAG;
    protected Bundle savedInstanceState;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //在界面未初始化之前调用的初始化窗口
        initWindows();
        if (initArgs(getIntent().getExtras())) {
            this.savedInstanceState = savedInstanceState;
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(getContentLayoutId());
            TAG = getComponentName().getShortClassName();
            initWidget();
            mModel = getModelImp();
            initData();
        } else {
            finish();
        }
    }

    protected abstract T getModelImp();

    /**
     * 初始化窗口
     */
    protected void initWindows() {

    }

    /**
     * 初始化相关参数
     *
     * @param bundle 参数bundle
     * @return 如果参数正确返回true, 错误返回false
     */
    protected boolean initArgs(Bundle bundle) {
        return true;
    }

    /**
     * 得到当前界面的资源文件Id
     *
     * @return 资源文件Id
     */
    protected abstract int getContentLayoutId();

    /**
     * 初始化控件
     */
    protected void initWidget() {

    }

    /**
     * 初始化数据
     */
    protected void initData() {

    }

    @Override
    public boolean onSupportNavigateUp() {
        //点击当前界面导航返回时,finish当前界面
        finish();
        return super.onSupportNavigateUp();
    }

    @Override
    public void onBackPressed() {
        //得到当前Activity下的所有Fragment
        List<Fragment> fragments = getSupportFragmentManager().getFragments();
        //判断集合是否为空
        if (fragments != null && fragments.size() > 0) {
            for (Fragment fragment : fragments) {
                //判断是否为我们能够处理的Fragment类型
                if (fragment instanceof BaseFragment) {
                    //是否拦截了返回按钮
                    if (((BaseFragment) fragment).onBackPressed()) {
                        //如果有,直接return
                        return;
                    }
                }
            }
        }
        super.onBackPressed();
        finish();
    }
}

接着是BaseFragment

/**
 * Fragment基类
 * Created by WaterWood on 2018/5/9.
 */
public abstract class BaseFragment<T extends MvcBaseModel> extends Fragment {

    protected T mModel;
    protected View mRoot;
    protected Activity activity;
    //日志打印标志
    protected String TAG;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        //初始化参数
        initArgs(getArguments());
        this.activity = activity;
        TAG = activity.getComponentName().getShortClassName();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (mRoot == null) {
            int layId = getContentLayoutId();
            //初始化当前的根布局,但是不在创建时就添加到container里面
            View root = inflater.inflate(layId, container, false);
            initWidget(root);
            mModel = getModelImp();
            mRoot = root;
        } else {
            if (mRoot.getParent() != null) {
                //把当前root从其父控件中移除
                ((ViewGroup) mRoot.getParent()).removeView(mRoot);
            }
        }
        return mRoot;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        //当View创建完成后初始化数据
        initData();
    }

    /**
     * 得到当前界面的资源文件Id
     *
     * @return 资源文件Id
     */
    protected abstract int getContentLayoutId();

    /**
     * 初始化控件
     */
    protected void initWidget(View root) {

    }

    /**
     * 初始化数据
     */
    protected void initData() {

    }

    /**
     * 初始化相关参数
     *
     * @param bundle 参数bundle
     * @return 如果参数正确返回true, 错误返回false
     */
    protected void initArgs(Bundle bundle) {

    }

    /**
     * 返回键触发时调用
     *
     * @return 返回true代表我已处理返回逻辑,Activity不用自己finish。
     * 返回false代表我没有处理逻辑,Activity自己走自己的逻辑
     */
    public boolean onBackPressed() {
        return false;
    }

    protected abstract T getModelImp();
}

其中的变化大家可以和之前的做一些比较,当然,直接拿来用也是可以的。

第三个,自然是我们的接口

public interface MvcBaseCallBack {
}

这个没什么基本上,不过之后如果有统一接口我们可以写在这里。

第四个是Model的基类

public class MvcBaseModel<T extends MvcBaseCallBack> {

    protected T callback;
    protected Context context;

    public MvcBaseModel(Context context,T callback) {
        this.context = context;
        this.callback = callback;
    }
}

Model基类构造函数要求传入上下文和Callback实现类。大家要注意传入的内容。

四个主要部分已经说明白了。终于是不报错了。不过大家可能还是不太明白怎么用。这里我给大家举个例子

public class DemoActivity extends BaseActivity<DemoModel> implements DemoCallback{

    @Override
    protected DemoModel getModelImp() {
        return new DemoModel(this,this);
    }

    @Override
    protected int getContentLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initWidget() {
        //初始化控件的操作
    }

    @Override
    protected void initData() {
        //网络请求等操作,要使用mModel必须在这里用
        mModel.requestWeb();
    }

    @Override
    public void success() {

    }
}
public interface DemoCallback extends MvcBaseCallBack{
    public void success();
}
public class DemoModel extends MvcBaseModel<DemoCallback>{
    public DemoModel(Context context, DemoCallback callback) {
        super(context, callback);
    }

    public void requestWeb(){
        callback.success();
    }
}

DemoCallback 中写的接口我不做过多说明,一般我们就是成功和失败。当然,如果页面请求了多个接口,可能这里就需要多对儿接口方法。每个成功和失败为一对儿。

DemoModel 中每个方法中会请求一个网络接口,接口返回成功用callback调用成功的接口方法,接口返回失败用callback调用失败的接口方法。对应的在Activity或Fragment中要实现接口的方法。

我们可以通过接口方法的参数将返回的结果从Model中传入Activity中。

这篇文章可能有些基础的同学比较容易看懂。不过你有任何问题都可以给我留言。我将给大家一一解答。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值