MVP+工厂模式的综合使用

MVP+工厂模式的综合使用

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

MVP的理解

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

实现过程

分析

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

视图模板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
接下来就是上图:
这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值