在应用中,用户进入应用首页以后经常会遇到顺序弹出多个弹窗的业务。例如进入首页以后,首先弹出运营活动弹窗,然后弹出应用评分或反馈弹窗,最后弹出应用更新弹窗等等。于是想到封装一套代码可以控制弹窗流程执行。
DialogChainOwner
弹窗链持有者。负责弹窗链节点的加入和展示入口。
/**
* 弹窗链拥有者,用于控制链节点的添加和展示以及取消,销毁
*/
public class DialogChainOwner implements LifecycleEventObserver {
private List<ChainNode> chainNodes = new ArrayList<>(); //链节点列表
private Set<Integer> cancelledIds; //取消执行的链节点集合
private boolean isDestroyed = false; //是否销毁
public DialogChainOwner(@NonNull LifecycleOwner owner) {
owner.getLifecycle().addObserver(this);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
destroy();
}
}
/**
* 加入链节点
*
* @param chainNode
* @return
*/
public DialogChainOwner join(ChainNode chainNode) {
chainNodes.add(chainNode);
return this;
}
//开始展示
public void show() {
DialogChain chain = new DialogChain(this, chainNodes, 0);
chain.proceed();
}
//销毁
public void destroy() {
isDestroyed = true;
chainNodes.clear();
if (cancelledIds != null) {
cancelledIds.clear();
}
}
/**
* 取消链节点
*
* @param id
*/
public void cancel(int id) {
if (cancelledIds == null) {
cancelledIds = new HashSet<>();
}
cancelledIds.add(id);
}
boolean isCancelled(int id) {
return cancelledIds != null && cancelledIds.contains(id);
}
boolean isDestroyed() {
return isDestroyed;
}
}
DialogChain
负责取对应的节点执行操作。
final class DialogChain {
private DialogChainOwner chainOwner;
private List<ChainNode> chainNodes;
private final int index;
DialogChain(DialogChainOwner owner, List<ChainNode> chainNodes, int index) {
this.chainOwner = owner;
this.chainNodes = chainNodes;
this.index = index;
}
final void proceed() {
if (chainOwner != null && chainOwner.isDestroyed()) {
destroy();
return;
}
if (chainNodes == null || index >= chainNodes.size()) return;
DialogChain next = new DialogChain(chainOwner, chainNodes, index + 1);
ChainNode chainNode = chainNodes.get(index);
if (chainOwner != null && chainOwner.isCancelled(chainNode.getId())) {
next.proceed();
} else {
chainNode.proceed(next);
}
}
void destroy() {
chainOwner = null;
chainNodes.clear();
}
}
ChainNode
链节点接口。弹窗实现该接口执行操作。
public interface ChainNode {
/**
* 返回链节点对于的Id
*
* @return
*/
int getId();
/**
* 处理链节点
*
* @param next 下一个弹窗链节点
*/
void proceed(DialogChain next);
}
示例
首先需要弹出的弹窗实现对应的链节点接口。
public class CustomDialog extends Dialog implements ChainNode {
private String content;
public CustomDialog(@NonNull Context context) {
super(context, R.style.CustomDialog);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_custom);
TextView textView = findViewById(R.id.content);
textView.setText(content);
}
public void setContent(String content) {
this.content = content;
}
@Override
public int getId() {
return 0;
}
@Override
public void proceed(DialogChain chain) {
show();
setOnDismissListener(dialog -> chain.proceed());
}
}
然后,依次加入对应的链接口并弹出。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DialogChainOwner owner = new DialogChainOwner(this);
CustomDialog dialog1 = new CustomDialog(this);
dialog1.setContent("第一个弹窗");
CustomDialog dialog2 = new CustomDialog(this);
dialog2.setContent("第二个弹窗");
CustomDialog dialog3 = new CustomDialog(this);
dialog3.setContent("第三个弹窗");
CustomDialog dialog4 = new CustomDialog(this);
dialog4.setContent("第四个弹窗");
owner.join(dialog1).join(dialog2).join(dialog3).join(dialog4).show();
}
}
感谢大家的支持,如有错误请指正,如需转载请标明原文出处!