神刀安全网

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

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

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

分析 AlertDialog

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

1.先来看看 AlertDialog 源码

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

AlertDialog源码中可以发现成员变量中有一个AlertController,从它的命名
可以了解它大概是个组织类,即是所谓的”控制层“;再从AlertDialog的构造方法中发现,它没做什么太多的操作,主要就是初始化了AlertController,那我们可以进一步了解到
AlertController可能是担任组织数据逻辑的作用。

那我们就进一步的看看

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

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

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

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

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

再看一看源码

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

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

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

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

create()方法中的apply()是将AlertDialog中的AlertControllerAlertController.AlertParams建立联系,其实就是控制层与逻辑层相通,最后会由
AlertController控制要显示的视图内容。

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

2.AlertController.AlertParams源码

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

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

3.AlertController 源码

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

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

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

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

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

构建视图的过程,通过获得的数据构建相应的视图内容。
所以说AlertController是整个模式中负责组织建造的,这也是Builder模式的核心。

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

Builder模式 实践

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

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模式写的BottomPopUpDialogBuildr模式是将一个对象的构建与显示分离,将不同的参数一个一个添加进去,也是对于外部隐藏实现细节,更是降低了耦合度,方便以后的自由扩展。还有,我的实现省去了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");

最后

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

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Android设计模式 Builder模式的分析与实践

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址