欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MVP+工厂模式的综合使用

程序员文章站 2022-04-05 17:49:39
...

MVP+工厂模式的综合使用

多次被部门老大说了自己代码写的就是垃圾以后,我就下定决心好好去学习编程的设计模式。刚好上一篇文章学了工厂模式,那就索性学习在安卓上的使用,这次结合了MVP模式,写了一个模板。

MVP的理解

MVP 中主要说一下P,Presenter翻译出来就是主持人,那么主持人的主要工作就是需要和前台观众互动,同时对接后台演员的表演,演员的表演是通过主持人来对接,主持人就起到一个中间人的作用。
那么在Android中也是这样的,数据和视图分开,数据(Mode)需要哪一个视图来展示,那就告诉Presenter来替他去找,同样的,视图(View)需要哪个数据,也是让Presenter替他去找。这样就很好的将数据和视图独立分开。
MVP+工厂模式的综合使用

实现过程

分析

首先需要创建一个模板View,相应的模板需要一些数据mode,还有就是中间人Presenter,本次还使用到工厂模式,因此还有两个工厂,一个是数据生产工厂,一个是视图生产工厂。看一下代码类命名:
MVP+工厂模式的综合使用

视图模板Template

package demo.pplive.com.vitem;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.facebook.drawee.view.SimpleDraweeView;

/**
 * @Createdby jixiongxu
 * @on 2017/9/28.
 * @description 模板视图
 */

public class Template extends BaseView
{
    private Context context;

    /**
     * 模板id
     */
    public final static String tid = "VItem";

    /**
     * 当前该节点的数据
     */
    private TemplateItemModel data = null;

    /**
     * w:h = 16:9
     */
    private static final float SCALE_W16_H9 = 1.7778F;

    /**
     * 最大的列数
     */
    private static final int MAX_COW = 2;

    /**
     * 最大行数
     */
    private int MAX_LINE = 0;

    /**
     * w:h = 3:4
     */
    private static final float SCALE_W3_H4 = 0.75F;

    /**
     * 屏幕宽度
     */
    private int width = 0;

    public Template(Context context)
    {
        this(context, null);
    }

    public Template(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        // 获取屏幕宽度,根据宽度和宽高比设置高度
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        width = wm.getDefaultDisplay().getWidth();
        this.context = context;
    }

    /**
     * 添加view到界面
     * 
     * @param context
     */
    private void addView(Context context)
    {
        int current = 0;
        LayoutParams param = new LayoutParams(width / MAX_COW, (int) (width / MAX_COW * SCALE_W3_H4));
        this.setOrientation(VERTICAL);
        for (int j = 0; j < MAX_LINE; j++)
        {
            // 添加一行
            LinearLayout layoutLine = new LinearLayout(context);
            layoutLine.setOrientation(HORIZONTAL);
            for (int i = 0; i < MAX_COW; i++)
            {
                if (current < data.modle.length)
                {
                    // 添加单个元素
                    View view = View.inflate(context, R.layout.item, null);
                    Holder holder = new Holder();
                    view.setLayoutParams(param);
                    view.setPadding(3, 0, 3, 0);
                    view.setTag(holder);
                    layoutLine.addView(view);
                    fillData(data.modle[current], view, holder);
                    current++;
                }
            }
            this.addView(layoutLine);
        }
    }

    /**
     * 填充单个布局的数据
     * 
     * @param data
     * @param view
     * @param holder
     */
    private void fillData(TemplateItemModel.Data data, View view, Holder holder)
    {
        holder.subtitle = (TextView) view.findViewById(R.id.subtitle);
        holder.img_context = (SimpleDraweeView) view.findViewById(R.id.img_context);
        holder.red_text = (TextView) view.findViewById(R.id.red_text);
        holder.img_title = (TextView) view.findViewById(R.id.img_title);
        holder.subtitle.setText(data.titlte);
        holder.img_context.setImageURI(data.img);
        holder.red_text.setText(data.red);
        holder.img_title.setText(data.description);
    }

    /**
     * 关联数据
     * 
     * @param data
     */
    public void setData(TemplateItemModel data)
    {
        if (data == null)
        {
            return;
        }
        this.data = data;
        if (data.modle.length % MAX_COW == 0)
        {
            MAX_LINE = data.modle.length / MAX_COW;
        }
        else
        {
            MAX_LINE = data.modle.length / MAX_COW + 1;
        }
        addView(context);
    }

    public class Holder
    {
        private SimpleDraweeView img_context;

        private TextView red_text;

        private TextView img_title;

        private TextView subtitle;
    }
}

数据基类TemplateModel

package demo.pplive.com.vitem;

/**
 * Created by jixiongxu on 2017/9/28.
 * 
 * @description 模板的整体数据
 */

public class TemplateModel
{
    /**
     * 模板id
     */
    public String tid;

    /**
     * 模板标题
     */
    public String title;

    /**
     * 请求码
     */
    public int requestCode;

}

单条数据TemplateItemModel

package demo.pplive.com.vitem;

/**
 * @Createdby jixiongxu
 * @on 2017/9/28.
 * @description Template数据
 */

public class TemplateItemModel extends TemplateModel
{
    /**
     * 单块详细数据
     */
    public Data[] modle;

    class Data
    {
        /**
         * 标题
         */
        public String titlte;

        /**
         * 描述
         */
        public String description;

        /**
         * 红色提示字符
         */
        public String red;

        /**
         * 跳转地址
         */
        public String link;

        /**
         * 图片地址
         */
        public String img;
    }

}

数据工厂DataFactory

package demo.pplive.com.vitem;

import com.google.gson.Gson;

/**
 * @Createdby jixiongxu
 * @on 2017/9/28.
 * @description 生产数据的工厂
 */

public class DataFactory
{
    private TemplateModel modle;

    /**
     * 获取得到的是所有的模板数据
     * 
     * @param gsonStr
     * @return
     */
    public TemplateModel getBaseModle(String gsonStr)
    {
        if (gsonStr == null || gsonStr.isEmpty())
        {
            return null;
        }
        Gson gson = new Gson();
        modle = gson.fromJson(gsonStr, TemplateModel.class);
        if ("VItem".equals(modle.tid))
            return getData(gsonStr, TemplateItemModel.class);
        else
            return null;
    }

    /**
     * 通过反射获取具体数据
     * 
     * @param srt
     * @param clz
     * @param <T>
     * @return
     */
    public <T extends TemplateModel> T getData(String srt, Class<T> clz)
    {
        Gson gson = new Gson();
        return (T) gson.fromJson(srt, TemplateItemModel.class);
    }
}

视图工厂ViewFractory

package demo.pplive.com.vitem;

import android.content.Context;

import android.view.View;

/**
 * @Createdby jixiongxu
 * @on 2017/9/28.
 * @description 生产view的工厂
 */

public class ViewFractory
{
    public View getView(String tid, Context context)
    {
        if (tid.equals(Template.tid))
        {
            return new Template(context);
        }
        else
        {
            return null;
        }
    }
}

中间人Presenter

package demo.pplive.com.vitem;

import android.content.Context;

/**
 * @Createdby jixiongxu
 * @on 2017/9/30.
 * @description MVP模式中的P,中间者
 */

    public class Presenter {

    /**
     * 有一些View需要自己访问网络操作
     * 只要传入模板id就可以自己去获取网络数据
     *
     * @param tid
     * @return
     */
    public static TemplateModel findDataByView(String tid) {
        if (tid.equals(Template.tid))
            return getDataByUrl(tid);
        else {
            return null;
        }
    }

    /**
     * 获取网络数据,具体方法还没写
     *
     * @param tid
     * @return
     */
    private static TemplateModel getDataByUrl(String tid) {

        if (tid.equals(Template.tid)) {
            String gsonStr = "";
            /**
             * 获取网络来的gson数据
             */
            //gsonStr = getGsonFromNet();
            DataFactory factory = new DataFactory();
            return factory.getBaseModle(gsonStr);
        } else {
            return null;
        }
    }

    /**
     * 通过数据获取模板
     *
     * @param modle
     * @return
     */
    public static BaseView findViewByData(TemplateModel modle, Context context) {
        ViewFractory factory = new ViewFractory();
        return (BaseView) factory.getView(modle.tid, context);
    }
}

使用MainActivity

package demo.pplive.com.vitem;

import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;

public class MainActivity extends Activity
{
    private String gson = "{\n" + "    \"tid\": \"VItem\",\n" + "    \"title\": \"this is title\",\n"
            + "    \"requestCode\": 200,\n" + "    \"modle\": [\n" + "        {\n"
            + "            \"titlte\": \"平凡岁月\",\n" + "            \"description\": \"朵朵告别舞台,大宝吃醋怒揍秦华\",\n"
            + "            \"red\": \"推荐\",\n"
            + "            \"link\": \"pptv://page/player/halfscreen?type=vod&vid=9043346\",\n"
            + "            \"img\": \"http://sr1.pplive.cn/cms/31/90/9b67d43ca616bc7d4c12dc20d7337f0a.jpg\"\n"
            + "        },\n" + "        {\n" + "            \"titlte\": \"春天里\",\n"
            + "            \"description\": \"兄弟情深共谱奋斗曲\",\n" + "            \"red\": \"推荐\",\n"
            + "            \"link\": \"pptv://page/player/halfscreen?type=vod&vid=9043344\",\n"
            + "            \"img\": \"http://sr4.pplive.cn/cms/10/47/0dbc833ea08126a5752f2822636878d5.jpg\"\n"
            + "        },\n" + "        {\n" + "            \"titlte\": \"新木乃伊\",\n"
            + "            \"description\": \"【阿汤哥新作】环球黑暗宇宙强势上线!\",\n" + "            \"red\": \"VIP免费\",\n"
            + "            \"link\": \"pptv://page/player/halfscreen?type=vod&vid=26363189\",\n"
            + "            \"img\": \"http://sr2.pplive.cn/cms/42/49/1f7dddf4a56149127862c713e423634b.jpg\"\n"
            + "        },\n" + "        {\n" + "            \"titlte\": \"PP动漫音乐控\",\n"
            + "            \"description\": \"初音未来殿堂精选第二弹\",\n" + "            \"red\": \"推荐\",\n"
            + "            \"link\": \"pptv://page/player/halfscreen?type=vod&vid=26683793&sid=8009046\",\n"
            + "            \"img\": \"http://sr1.pplive.cn/cms/16/07/10b2aeb82799541342d892a49cf82b8c.jpg\"\n"
            + "        },\n" + "        {\n" + "            \"titlte\": \"申鑫能否翻盘一黑到底\",\n"
            + "            \"description\": \"正播足协杯半决赛次回合\",\n" + "            \"red\": \"推荐\",\n"
            + "            \"link\": \"pptv://page/player/halfscreen?type=live&vid=304349\",\n"
            + "            \"img\": \"http://sr1.pplive.cn/cms/39/22/6c048037e9ee8c9c02c8ce2184436a11.jpg\"\n"
            + "        },\n" + "        {\n" + "            \"titlte\": \"抢24个月影视VIP!\",\n"
            + "            \"description\": \"阿汤哥送你12个月影视VIP!\",\n" + "            \"red\": \"VIP用卷\",\n"
            + "            \"link\": \"http://vip.pptv.com/activity/2017/xinmunaiyi/h5/dsy?plt=app\",\n"
            + "            \"img\": \"http://sr4.pplive.cn/cms/24/91/b6325b2e676cf28dadb4e83f340b425d.jpg\"\n"
            + "        }\n" + "    ]\n" + "}";

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        LinearLayout layout = (LinearLayout) findViewById(R.id.layout_main);
        DataFactory factory = new DataFactory();
        TemplateItemModel modle = (TemplateItemModel) factory.getBaseModle(gson);
        Template template = (Template) Presenter.findViewByData(modle, this);
        template.setData(modle);
        layout.addView(template);
    }
}

剩下的其他代码我继不列出来了,有兴趣的也可以去我的Gitup上下载,git地址
gitup:https://github.com/jixiongxu/VItem.git
接下来就是上图:
MVP+工厂模式的综合使用

相关标签: mvp