MVP+工厂模式的综合使用
程序员文章站
2022-04-05 17:49:39
...
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
接下来就是上图:
推荐阅读