采用Build模式构建自定义Dialog

来源:互联网 发布:打开xlsx文件的软件 编辑:程序博客网 时间:2024/05/29 19:18

先说Build的概念,我看到网上有很多关于这个模式的解释说明,我比较认同的是下面的这种理解:
所谓Build模式就是:一步一步将一个复杂对象创建出来,允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程。

我们最深的体会就是链式编程的运用,这里面基本上都是创建了一个内部静态Build. Android中尤为常见,比如说AlertDialog. 我这里就拿自己做的一个Dialog仿照AlertDialog,运用Build模式来创建,可能封装得有些不完整,但是我一开始的目的就是希望能用到链式编程,所以就算不完整,我还是拿来作为案例讲解。

1.效果图:

这里写图片描述

2. 没有运用Build模式的写法:

可以看到这个Dialog中,需要传递的参数非常多,总计有8个,按照普通写法,可能在new Dialog中需要一次性传递8个参数,不要笑话我,我开始赶进度的时候确实是这么做的。

 public EffectDialog(Context context, int themeResId,String effect,String visit,String praise,                        String comment,String share,String collection,String reward,String speed) {        super(context, themeResId);        mEffect = effect;        mVisit = visit;        mPraise = praise;        mComment = comment;        mShare = share;        mCollection = collection;        mReward = reward;        mSpeed = speed;    }

然后在调用的地方,使劲的传参数,还时不时看有没有传错位。太痛苦了。
然后痛定思痛,开始改造。

3. 改造成Build模式

先看源码AlertDialog, 有个AlertController

private AlertController mAlert;

还有个内部静态类Builder,我这里只摘抄几个方法:

public static class Builder {    private final AlertController.AlertParams P;     public Builder(Context context) {            this(context, resolveDialogTheme(context, 0));        }    public Builder setTitle(CharSequence title) {            P.mTitle = title;            return this;        }..........

还有个就是要看AlertDialog的OnCreate方法:

 @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mAlert.installContent();    }

从这里,我们就应该可以看出:AlertDialog中需要的成员变量,封装到AlertController中,通过Build设置的参数,都是 赋值给了AlertController.AlertParams P。示意图就是:
AlertDialog《===AlertController《===Build

我不想做那么复杂,就省略掉AlertController, 直接用Dialog和Build类。Build类中赋值都是赋值给Dialog中的成员变量,setView的操作直接交给Dialog自己做,不需要封装到Build类中,示意图为:
EffectDialog <===Build

先看Build能做的事情:设置成员变量的值和一个listener. 仔细看AlertDialog 的Build,里面封装的远远不止这些,在这里我只封装这么多够用了。

 public static class Builder{        private EffectDialog mDialog;        public Builder(Context context, int themeResId){            mDialog = new EffectDialog(context,themeResId);        }        public Builder setEffect(String effect){            mDialog.mEffect = effect;            return this;        }        public Builder setPraise(String praise){            mDialog.mPraise = praise;            return this;        }        public Builder setVisit(String visit){            mDialog.mVisit = visit;            return this;        }        public Builder setComment(String comment){            mDialog.mComment = comment;            return this;        }        public Builder setShare(String share){            mDialog.mShare = share;            return this;        }        public Builder setCollection(String collection){            mDialog.mCollection = collection;            return this;        }        public Builder setReward(String reward){            mDialog.mReward = reward;            return this;        }        public Builder setSpeed(String speed){            mDialog.mSpeed = speed;            return this;        }        public Builder setOnMyShareListener(MyShareListener listener){            mDialog.myListener= listener;            return this;        }        public EffectDialog createDialog(){            return mDialog;        }    }

再看Dialog自己能做的事情:setContentView(), 这个可以交给Build做,但是我觉得用Dialog自己处理比较好,就没有封装到Build类中了。还有一个就是自己定义的接口MyShareListener,刚开始也是交给Dialog自己做,但是看到AlerDialog中也是交给了Build,所以也模仿了一次,交给了Builder。

public class EffectDialog extends Dialog implements View.OnClickListener{private TextView mTvEffect;//影响因子private TextView mTvVisit;//浏览量private TextView mTvPraise;//点赞数private TextView mTvComment;//评论数private TextView mTvshare;//分享数private TextView mTvCollection;//收藏数private TextView mTvReward;//打赏人次private TextView mTvSpeed;//首次阅读速度private Button mBtnShare;//分享出去private ImageView mIvClose;//关闭private String mEffect;private String mVisit;private String mPraise;private String mComment;private String mShare;private String mCollection;private String mReward;private String mSpeed;private  MyShareListener myListener; public EffectDialog(Context context, int themeResId) {        super(context, themeResId);    } @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.dialog_effect);        initView();        setClickListener();    }private void initView() {        mTvEffect = (TextView) findViewById(R.id.tv_effect);        mTvVisit = (TextView) findViewById(R.id.tv_visit);        mTvPraise = (TextView) findViewById(R.id.tv_praise);        mTvComment = (TextView) findViewById(R.id.tv_comment);        mTvshare =(TextView) findViewById(R.id.tv_share);        mTvCollection = (TextView) findViewById(R.id.tv_collection);        mTvReward =  (TextView) findViewById(R.id.tv_reward);        mTvSpeed = (TextView) findViewById(R.id.tv_speed);        mIvClose = (ImageView) findViewById(R.id.iv_close);        mBtnShare = (Button) findViewById(R.id.btn_share);        mTvEffect.setText(mEffect);        mTvVisit.setText(mVisit);        mTvPraise.setText(mPraise);        mTvComment.setText(mComment);        mTvshare.setText(mShare);        mTvCollection.setText(mCollection);        mTvReward.setText(mReward);        mTvSpeed.setText(mSpeed);    }    private void setClickListener() {        mIvClose.setOnClickListener(this);        mBtnShare.setOnClickListener(this);    }    @Override    public void onClick(View v) {        if(v.getId()==R.id.iv_close){            dismiss();        }else if(v.getId()==R.id.btn_share){            if(myListener!=null){                myListener.onMyShare();                dismiss();            }        }    } public interface MyShareListener {        void onMyShare();    }}

最后再看看如何调用:

/**没有Build模式,用的是这中方法*///EffectDialog dialog = new EffectDialog(mContext,R.style.AlertDialogStyle,                           //dataBean.getAFFECT_NUM(),dataBean.getVIEWNUM(),dataBean.getPRAISENUM(),                           //dataBean.getCOMMENTNUM(),dataBean.getSHARENUM(),dataBean.getCOLLECTIONNUM(),//                            dataBean.getREWARDNUM(),dataBean.getVIEW_SPEED());/**用了Build模式之后:链式调用*/EffectDialog dialog = new EffectDialog.Builder(mContext,R.style.AlertDialogStyle)                            .setVisit(dataBean.getVIEWNUM())                            .setSpeed(dataBean.getVIEW_SPEED())                            .setCollection(dataBean.getCOLLECTIONNUM())                            .setComment(dataBean.getCOMMENTNUM())                            .setShare(dataBean.getSHARENUM())                            .setEffect(dataBean.getAFFECT_NUM())                            .setReward(dataBean.getREWARDNUM())                            .setPraise(dataBean.getPRAISENUM())                            .setOnMyShareListener(new EffectDialog.MyShareListener() {                                @Override                                public void onMyShare() {                                    showShareDialog(dataBean);                                }                            })                            .createDialog();                    dialog.show();}

好了,以上就是用Build模式写的一个Dialog,当然封装得不彻底,不过能达到我最初想要的链式编程目的,后面如果深入的话,希望能封装得更彻底,更好。

0 0