在MVP模式里通常包含4个要素:
(1)View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
(2)View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
(3)Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
(4)Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
MVP与MVC架构图:
通过上述两幅图我们可以看出MVP与MVC模式的最大区别在于Model并不与View直接交互,MVP中presenter与view进行交互,这种交互依赖于接口实现,更有利于进行单元测试,通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑 。
说的再多,也不如代码来的明显,接下来我们就一起实现吧。
目标就是实现上一篇中的自定义VIEW,没有看过?那就去看看吧。传送们。
首先我们还是把RectModel
实体类拿过来,考虑到篇幅原因,就不在这里粘代码了,这样我们的Model层就完成了,下一步到Presenter层,新建CircualRectPresenter
接口,新建CircualRectPresenterImpl
类继承自CircualRectPresenter
,最后是View
层,新建CircualRectView
继承自View
。至此我们就完成了整个大MVP框架的搭建,项目结构如下图:
看着好像还不错喔,还等什么keep go on吧。
在CircualRectPresenter
接口中添加如下函数:
void draw(Canvas canvas);
在CircualRectPresenterImpl
类中添加如下代码:
private Context mContext;
private int mViewWidth,mViewHeight;
private Paint mRectPaint,mTextPaint,mLinePaint;
private List<String> mDrawingText;
private List<RectModel> mRectModels;
private int mCenterRectHeight = 50;
private int mChildRectDistance = 200 ;
private int mSingleChildDegreeDistance;
public CircualRectPresenterImpl(Context mContext, int mViewWidth, int mViewHeight) {
this.mContext = mContext;
this.mViewWidth = mViewWidth;
this.mViewHeight = mViewHeight;
init(mContext);
}
@Override
public void draw(Canvas canvas) {
/*
* 绘制中心节点
* */
RectModel rectModel = new RectModel(MeasureUtils.getRect(mViewWidth/2,mViewHeight/2,mDrawingText.get(0).length()*20,mCenterRectHeight),mDrawingText.get(0),0);
mRectModels.add(rectModel);
drawNode(canvas,rectModel);
/*
* 画周围子节点
* */
mSingleChildDegreeDistance = 360 / (mDrawingText.size()-1);
for (int i=0;i<mDrawingText.size()-1;i++){
RectModel rectModel1 = new RectModel(MeasureUtils.getRect(mChildRectDistance+mViewWidth/2,mViewHeight/2,mDrawingText.get(i+1).length()*20,mCenterRectHeight),mDrawingText.get(i+1),i*mSingleChildDegreeDistance);
mRectModels.add(rectModel1);
drawNode(canvas,rectModel1);
canvas.drawLine(mViewWidth/2,mViewHeight/2,rectModel1.getCenterX(),mViewHeight/2,mLinePaint);
canvas.rotate(mSingleChildDegreeDistance,mViewWidth/2,mViewHeight/2);
}
}
public void init(Context context){
mContext = context;
mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint = new Paint();
mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRectPaint.setStyle(Paint.Style.FILL);
mRectPaint.setColor(Color.BLUE);
mTextPaint.setStrokeWidth(3);
mTextPaint.setColor(Color.RED);
mLinePaint.setColor(Color.BLUE);
mRectModels = new ArrayList<>();
mDrawingText = new ArrayList<>();
mDrawingText.add("中心节点");
mDrawingText.add("节点1");
mDrawingText.add("节点2");
mDrawingText.add("节点3");
mDrawingText.add("节点4");
mDrawingText.add("节点5");
mDrawingText.add("节点6");
mDrawingText.add("节点7");
}
public void drawNode(Canvas canvas,RectModel rectModel){
/*
* 锁定画布,将画布旋转回原始坐标系
* */
canvas.save();
canvas.rotate(-rectModel.getAngle(),rectModel.getCenterX(),rectModel.getCenterY());
canvas.drawRect(rectModel.getLeft(),rectModel.getTop(),rectModel.getRight(),rectModel.getBottom(),mRectPaint);
Paint.FontMetricsInt fontMetrics = mRectPaint.getFontMetricsInt();
int baseline = (rectModel.getBottom() + rectModel.getTop() - fontMetrics.bottom - fontMetrics.top) / 2;
mTextPaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(rectModel.getText(), rectModel.getCenterX(), baseline, mTextPaint);
/*
* 释放画布
* */
canvas.restore();
}
完成以后接下来就是将presenter和View绑定喽:CircualRectView代码如下:
public class CircualRectView extends View {
public void setCircualRectPresenter(CircualRectPresenter circualRectPresenter) {
this.circualRectPresenter = circualRectPresenter;
}
private CircualRectPresenter circualRectPresenter;
public CircualRectView(Context context) {
super(context);
}
public CircualRectView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircualRectView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
circualRectPresenter.draw(canvas);
super.onDraw(canvas);
}
}
最后在activity为CircualRectView注入presenter:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CircualRectView circualRectView = new CircualRectView(this);
CircualRectPresenterImpl circualRectPresenter = new CircualRectPresenterImpl(this, MeasureUtils.getScreenWidth(this),MeasureUtils.getScreenHeight(this));
circualRectView.setCircualRectPresenter(circualRectPresenter);
setContentView(circualRectView);
}
}
运行效果如下图:
与上一次效果无差异,哈哈哈,快动手试一下吧。完整源码:传送门
最新文章更新在微信公众号上,欢迎关注获取详情: