前言
- 在实际业务中,我们经常会遇到类似activity在实现具体业务,在回调改变view视图。也就是我们常说的MVP,或者MVVM或者MVVVM。如果是涉及到的弹窗地方,并且有复杂的业务组合呢?这时候代码书写该怎么办呢?不知道各位在实际操作中是怎么样来做的
- 如果这么说很抽象的话, 不如来设想一下类似微信红包业务的弹窗业务。因此笔者采用MVP的思想。封装了一个弹窗的library。
项目
https://github.com/cxMax/Popup
- 废话不说先上项目,有兴趣的可以看下readme.md,用法和各个类的用途也写得比较清楚了。
用法
- 再说具体代码实现的话,先说用法吧。很简单,使用者只需要关心四个步骤即可。
- 第一步:JavaBean类, 弹窗业务相关的实体类, 也就是服务端返回的json实例对象
- 第二步: 弹窗的view类,即初始化view,以及业务回调改变view的类。继承AbsPopupProvider类,类似CouponProvider.
Override以下方法:
onCreateView() 弹窗的布局layout
initView() 初始化弹窗相关的控件
updateView() 数据的绑定
initOperation() 初始化处理具体弹窗(内部控件点击)业务逻辑类
showPopupView() 显示的位置,默认在屏幕中央
第三步:弹窗的业务类,继承AbsPopupOperation类, 类似CouponOperation.
具体的控件点击交互事件可以在PopupOperation接口中定义或者拓展,PopupOperation.PopupView作为view交互的回调事件定义。第四步:在需要显示弹窗的地方调用popup的链式调用即可。
Popup.with(this)
.windowHeight(390)
.windowWidth(300)
.data(data)
.background(R.drawable.game_gift_popupwindow_use_background)
.clz(CouponProvider.class)
.apply()
.showPopupView();
代码
- 项目目录截图:
- 相关类说明:
- PopupOptions 弹窗相关的属性
- GeneratorTool , Generator , DialogGenerator , PopupGenerator 具体dialog and popupwindow初始化的代码。
- AbsPopupProvider, 弹窗view的init和change,都在这个类
- AbsPopupOperation , 弹窗view的交互逻辑
- Popup , 对外提供的一个链式调用 , 调用的参数包含弹窗的一些属性。
- AnimatorUtil 弹窗交互动画util类
优缺点
优点:
- 使用这个lib来构建窗体,可以节省代码成本。(参考使用步骤)
- 解决BadTokenException。 ps:相信异步请求回调触发弹窗的需求,很多同学都遇到过这个bug吧
解决方案:
1.配合rxlivecycle的调用 , 在当前生命周期结束的时候,会cancle掉此次请求
2.Popup.with(this),的实现参考了glide源代码, 这次传递activity 或者 fragment 作为context,会在弹窗调用show()方法的时候,判断当前activity/fragment的生命周期情况 - 增加动画接口,和弹窗样式接口.相关属性可以直接在style中配置调用,是不是很方便~
缺点:
- 在AbsPopupProvider的createView() ; PopupGenerator的create(); DialogGenerator的create(); 代码还可以更优雅的处理.
- 关于整个popup的链式调用设计,我觉得可能存在一点缺陷,以下方法必须调用.但方法调用顺序可随意更改.
作为优化点, 我在想, 链式调用设计可不可划分为两部分,即非必须参数,和必须参数.直白一点就是,以下调用的必要参数,作为(Object… params)只要调用一次就可以了.类似于glide的transform()的调用
Glide.with(context)
.transform(new XXTransformation()
, new XXTransformation()
, new CenterCrop(context));
最后
- 如果有什么疑问,或者代码有什么更好的建议,欢迎私信或者直接留言。