android设计模式分析,Android设计模式 Builder模式的分析与实践

之前实现了一个Demo底部弹出框,是用DialogFragment实现的一个Dialog,虽然实现了链式调用,但是没有使用Builder模式,所以想试试Builder模式,写博客记录一下。

这篇博客谈论的Android中的Builder模式没有Java传统的使用那么复杂,只是一种编程思路,使需要复杂的参数构建的对象变得简单,而且内部封装构建过程可以方便变换和复用,更是降低了耦合性。

分析 AlertDialog

AlertDialog是谷歌原生的对话框,在V7包中提供了Material Design设计风格的Dialog,使用非常广泛。但是,在这篇博客里,我们只讨论分析它的编程实现模式,它使用的就是Builder模式。

1.先来看看 AlertDialog 源码

img1.png?raw=true

从AlertDialog源码中可以发现成员变量中有一个AlertController,从它的命名

可以了解它大概是个组织类,即是所谓的”控制层“;再从AlertDialog的构造方法中发现,它没做什么太多的操作,主要就是初始化了AlertController,那我们可以进一步了解到

AlertController可能是担任组织数据逻辑的作用。

那我们就进一步的看看

img2.png?raw=true

往下阅读它的源码,AlertDialog在onCreate中与AlertController建立了联系,从它的方法命名installContent()可以了解它是初始化AlertDialog内容实体的,那我们可以确定刚刚的推测,AlertController是负责AlertDialog组织内容逻辑的,而AlertDialog只是简单的”UI层“。

再往下就是AlertDialog中静态内部类,也是我们要说的重点Builder

img3.png?raw=true

从Builder类中发现了一个眼熟的东西——AlertController.AlertParams,从它的命名(命名果然好重要)可以发现它可能是逻辑类,也就是”模型层“(是不是有点像MVC = =),负责处理数据逻辑的。

再看一看源码

img4.png?raw=true

跟推测的一样,直接把数据赋予给了AlertController.AlertParams,而且都是return Builder 对象,保证了链式调用;源码里面大部分都是类似的代码,这里只贴出部分。

在源码的最后,发现了重点

img5.png?raw=true

在create()方法中的apply()是将AlertDialog中的AlertController与AlertController.AlertParams建立联系,其实就是控制层与逻辑层相通,最后会由

AlertController控制要显示的视图内容。

AlertDialog的源码基本上我们过了一遍,了解它的模式思路,那我们再从apply()进去,看看AlertController与AlertController.AlertParams是怎么建立联系的。

2.AlertController.AlertParams源码

img10.png?raw=true

从代码中可以看见,AlertController获得了AlertController.AlertParams中保存的数据,其他代码不在详述,无非就是转换数据,最后还是要赋予AlertController。

3.AlertController 源码

img7.png?raw=true

在构造方法中获得相对应的视图。

img8.png?raw=true

这是之前介绍过的初始化实体内容的方法,显然是负责构建视图的。

img11.png?raw=true

构建视图的过程,通过获得的数据构建相应的视图内容。

所以说AlertController是整个模式中负责组织建造的,这也是Builder模式的核心。

通过分析AlertDialog的源码,我们了解谷歌原生组件的Builder的模式,通过分层将逻辑简化,代码简洁。

Builder模式 实践

根据以上,我使用Builder模式重构了之前的小项目BottomPopUpDialog。

public class BottomPopUpDialog extends DialogFragment {

private TextView mCancel;

private LinearLayout mContentLayout;

private Builder mBuilder;

private static BottomPopUpDialog getInstance(Builder builder) {

BottomPopUpDialog dialog = new BottomPopUpDialog();

dialog.mBuilder = builder;

return dialog;

}

@Override

public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {

super.onViewCreated(view, savedInstanceState);

//该方法需要放在onViewCreated比较合适, 若在 onStart 在部分机型(如:小米3)会出现闪烁的情况

getDialog().getWindow().setBackgroundDrawableResource(mBuilder.mBackgroundShadowColor);

}

@Override

public void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Holo_Light_NoActionBar);

}

@Nullable

@Override

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

View view = inflater.inflate(R.layout.bottom_pop_up_dialog, null);

initView(view);

registerListener(view);

setCancelable(true);

return view;

}

private void initView(View view) {

mContentLayout = (LinearLayout) view.findViewById(R.id.pop_dialog_content_layout);

mCancel = (TextView) view.findViewById(R.id.cancel);

initItemView();

}

private void registerListener(View view) {

view.setOnTouchListener(new View.OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

if (event.getAction() == MotionEvent.ACTION_DOWN) {

dismiss();

}

return false;

}

});

mCancel.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

dismiss();

}

});

}

@Override

public void show(FragmentManager manager, String tag) {

try {

super.show(manager, tag);

} catch (Exception e) {

e.printStackTrace();

}

}

private void initItemView() {

//循环添加item

for (int i = 0; i < mBuilder.mDataArray.length; i++) {

final PopupDialogItem dialogItem = new PopupDialogItem(getContext());

dialogItem.refreshData(mBuilder.mDataArray[i]);

//最后一项隐藏分割线

if (i == mBuilder.mDataArray.length - 1) {

dialogItem.hideLine();

}

//设置字体颜色

if (mBuilder.mColorArray.size() != 0 && mBuilder.mColorArray.get(i) != 0) {

dialogItem.setTextColor(mBuilder.mColorArray.get(i));

}

if (mBuilder.mLineColor != 0) {

dialogItem.setLineColor(mBuilder.mLineColor);

}

mContentLayout.addView(dialogItem);

dialogItem.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

mBuilder.mListener.onDialogClick(dialogItem.getItemContent());

if (mBuilder.mIsCallBackDismiss) dismiss();

}

});

}

}

public static class Builder {

private String[] mDataArray;

private SparseIntArray mColorArray = new SparseIntArray();

private BottomPopDialogOnClickListener mListener;

private int mLineColor;

private boolean mIsCallBackDismiss = false;

private int mBackgroundShadowColor = R.color.transparent_70;

/**

* 设置item数据

*/

public Builder setDialogData(String[] dataArray) {

mDataArray = dataArray;

return this;

}

/**

* 设置监听item监听器

*/

public Builder setItemOnListener(BottomPopDialogOnClickListener listener) {

mListener = listener;

return this;

}

/**

* 设置字体颜色

*

* @param index item的索引

* @param color res color

*/

public Builder setItemTextColor(int index, int color) {

mColorArray.put(index, color);

return this;

}

/**

* 设置item分隔线颜色

*/

public Builder setItemLineColor(int color) {

mLineColor = color;

return this;

}

/**

* 设置是否点击回调取消dialog

*/

public Builder setCallBackDismiss(boolean dismiss) {

mIsCallBackDismiss = dismiss;

return this;

}

/**

* 设置dialog背景阴影颜色

*/

public Builder setBackgroundShadowColor(int color) {

mBackgroundShadowColor = color;

return this;

}

public BottomPopUpDialog create() {

return BottomPopUpDialog.getInstance(this);

}

public BottomPopUpDialog show(FragmentManager manager, String tag) {

BottomPopUpDialog dialog = create();

dialog.show(manager, tag);

return dialog;

}

}

public interface BottomPopDialogOnClickListener {

/**

* item点击事件回调

*

* @param tag item字符串 用于识别item

*/

void onDialogClick(String tag);

}

}

这是我结合前面的Builder模式写的BottomPopUpDialog。Buildr模式是将一个对象的构建与显示分离,将不同的参数一个一个添加进去,也是对于外部隐藏实现细节,更是降低了耦合度,方便以后的自由扩展。还有,我的实现省去了Controller层代码,我把控制层和UI层放在一起,这样实现是为了简单,我觉得Controller层是在可以复用的场景下,使用起来更有价值,而小组件可以更简单的使用Builder模式。编程是简单实用。

重构之后的调用

new BottomPopUpDialog.Builder()

.setDialogData(getResources().getStringArray(R.array.popup_array))

.setItemTextColor(2, R.color.colorAccent)

.setItemTextColor(4, R.color.colorAccent)

.setCallBackDismiss(true)

.setItemLineColor(R.color.line_color)

.setItemOnListener(new BottomPopUpDialog.BottomPopDialogOnClickListener() {

@Override

public void onDialogClick(String tag) {

Snackbar.make(view, tag, Snackbar.LENGTH_LONG)

.setAction("Action", null).show();

}

})

.show(getSupportFragmentManager(), "tag");

最后

这是一个简单的编程模式,记录一下思路。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值