TheMVP 跟着代码走,绝对能实现(超简单)

论坛 期权论坛 脚本     
匿名技术用户   2020-12-22 14:30   236   0

一、关于TheMVP的优缺点:访问此网站有详细讲解https://kymjs.com/code/2015/11/09/01/

本文仅提供TheMVP框架代码(废话少说上代码):

model层其实就是存放我们需要的实体类。及其他数据。本文测试未使用,所以就没有写。

基本框架模型:

1.建包View

1.1view包下创建接口 IDelegate 定出规范:

package com.example.dw.dw20181121moni.view;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public interface IDelegate {
    //初始化方法
    void initData();
    //获取布局
    void create(LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle);
    //获取视图
    View getRootView();
    //获取上下文
    void getContext(Context context);
}

1.2 view包下创建抽象类 AppDelegate 实现接口 IDeltegate

initData和getContext在这里无用,我把这两个方法此类里删除掉了。另外可以在这里写两个方法,一个get()我是用来获取控件ID,一个setClick()我用来设置点击事件,这样在我的子presenter层只需要get(R.id.xxx);就可以获取的我的控件,而点击事件就更简单了,我只需要setClick(this.R.id.xxx);就可以设置我的点击事件。

我们要在这里拿到我们的layout,但是目前并不存在,所以定义一个抽象方法(getLayoutId()),在我们子persenter继承我们的AppDelete的时候,将对应的layout传过来。这个类只需要以下代码这些操作便完成了(你完全可以在这个类定义任何你觉得可以简化代码的方法,比如Toast)

package com.example.dw.dw20181121moni.view;

import android.os.Bundle;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public abstract class AppDelegate implements IDelegate {

    private View rootView;

    //获取布局
    @Override
    public void create(LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle) {
        rootView = inflater.inflate(getLayoutId(), viewGroup, false);
    }
    
    protected abstract int getLayoutId();

    //获取视图
    @Override
    public View getRootView() {
        return rootView;
    }

    //获取控件
    SparseArray<View> views = new SparseArray<>();
    public <T extends View> T get(int id){
        View view = views.get(id);
        if (view == null){
            view = rootView.findViewById(id);
            views.put(id,view);
        }
        return (T) view;
    }

    //点击方法
    public void setClick(View.OnClickListener listener,int...ids){
        if (ids == null){
            return;
        }
        for(int id:ids){
            get(id).setOnClickListener(listener);
        }
    }
}

2.创建presenter包

2.1 presenter包下创建BaseActivityPresenter作为Activity的基类,每一个Activity都对应一个子presenter

这里的 protected T presenter;没有使用private声明,因为某些情况下我们的presenter需要用到Activity(Fragment)的生命周期来进行某些操作,但是我们的子presenter继承的是AppDelegate无法调用生命周期,所以我们可以从Activity(Fragment)中调用生命周期,并在其中创建方法通过presneter.xX();达到我们的目的。

注意:getContext()方法是要在initData()之前调用,否则一些使用context的方法会找不到context。

package com.example.dw.dw20181121moni.presenter;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

import com.example.dw.dw20181121moni.view.IDelegate;

public abstract class BaseActivityPresenter<T extends IDelegate> extends AppCompatActivity {

    protected T presenter;
    
    //每一个Activity都对应一个Presenter
    public abstract Class<T> getPresenter();
    public BaseActivityPresenter(){
        try {
            presenter = getPresenter().newInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //创建布局
        presenter.create(getLayoutInflater(),null,savedInstanceState);
        //创建视图
        setContentView(presenter.getRootView());
        //获取context
        presenter.getContext(this);
        //初始化方法
        presenter.initData();
    }
}

2.2 presenter包下创建BaseFragmentPresenter,做为Fragment的基类

具体操作与BaseActivity相差不多,不多解释

package com.example.dw.dw20181121moni.presenter;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.dw.dw20181121moni.view.IDelegate;

public abstract class BaseFragmentPresenter<T extends IDelegate> extends Fragment {
    protected T presenter;
    //每一个Fragment都对应一个Presenter
    public abstract Class<T> getPresenter();
    public BaseFragmentPresenter(){
        try {
            presenter = getPresenter().newInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (java.lang.InstantiationException e) {
            e.printStackTrace();
        }
    }
    
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //创建布局
        presenter.create(inflater,container,savedInstanceState);
        //返回视图
        return presenter.getRootView();
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //获取context
        presenter.getContext(getContext());
        //初始化方法
        presenter.initData();
    }
}

3. 使用测试,很简单的几步,TheMVP的框架就已经搭好了。

接下来使用测试一下

3.1在presenter包下创建MainActivity对应的presneter, MainActivitypresenter继承AppDelegate处理所有逻辑

package com.example.dw.dw20181121moni.presenter;

import android.content.Context;

import com.example.dw.dw20181121moni.R;
import com.example.dw.dw20181121moni.view.AppDelegate;

public class MainActivityPresenter extends AppDelegate {

    private Context context;

    //返回视图
    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    //初始化方法
    @Override
    public void initData() {
        
    }

    //获取context
    @Override
    public void getContext(Context context) {
        this.context = context;
    }
}

3.2 MainActivity不再继承AppCompatActivity而是继承我们的BaseActivityPresenter,实现抽象方法getPresenter(),返回我们Activity对应的一个MainActivityPresenter.

package com.example.dw.dw20181121moni.activity;

import com.example.dw.dw20181121moni.presenter.BaseActivityPresenter;
import com.example.dw.dw20181121moni.presenter.MainActivityPresenter;

public class MainActivity extends BaseActivityPresenter<MainActivityPresenter> {
    @Override
    public Class getPresenter() {
        //返回对应的presenter
        return MainActivityPresenter.class;
    }
}

3.3简单在activity_main xml下写两个控件用来测试我们的框架

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.MainActivity">
   <TextView
       android:id="@+id/main_TextView"
       android:textSize="20sp"
       android:text="测试"
       android:layout_width="wrap_content"
       android:layout_height="match_parent" />
    <Button
        android:id="@+id/main_Button"
        android:text="点击改变TextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</RelativeLayout>
3.4在MainActivityPresenter中的initData()中,
通过get()方法找到main_TextView,
并且通过setClick()给main_Button设置点击事件.测试成功后,我们的框架就没有问题了。

没有最好的只有最合适的,选择最适合自己的,适合自己项目的框架才是王道!

package com.example.dw.dw20181121moni.presenter;

import android.content.Context;
import android.view.View;
import android.widget.TextView;

import com.example.dw.dw20181121moni.R;
import com.example.dw.dw20181121moni.view.AppDelegate;

public class MainActivityPresenter extends AppDelegate implements View.OnClickListener {

    private Context context;
    private TextView main_textView;

    //返回视图
    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    //初始化方法
    @Override
    public void initData() {
        main_textView = get(R.id.main_TextView);
        setClick(this,R.id.main_Button);
    }

    //获取context
    @Override
    public void getContext(Context context) {
        this.context = context;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.main_Button:
                main_textView.setText("测试成功");
                break;
        }
    }
}
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP