最近因为项目需求,需要完成一个全局的网络加载弹窗需求,真正完成这个需求之后,感觉最重要的不是结果,而是思维。
我刚开始接到这个需求的时候,第一种想到的方案是 基类加单例。但是实际做起来之后发现,因为单例的原因,你的弹窗只能在第一次创建这个单例的activity中显示出来。
那么发现这个问题之后在这个的基础上改进一下,如果我不用activity的上下文,而是采用类似于Application的一种全局上下文呢?当然,个人能力有限,这种想法就给毙掉了,后来由导师指点,利用service的上下文,dialog的style设置为系统级弹窗,那么这时候就会有一种潜在的情况,如果APP退到后台的话,加载网络的时候不管用户在那个页面,都会显示这个弹窗,严重影响用户体验。
后来把思路又回到起点,需要实现两个点,一:全局可调用。二:单一实例。
总结一下遇到的问题,
一:dialog必须依赖activity
二:因为单例的原因,dialog只能在第一次创建单例的activity显示
三:不能使用系统级弹窗
OK,基于这些问题和要求,想到用一个专门的activity去承载这个dialog。于是做出来一个demo简单测试了一下,当时并没有发现什么问题,但是实际应用到项目中之后发现,因为一个项目的逻辑远比demo复杂,所以就出现了activity生命周期的意外情况。因为我在onResume()方法中写了刷新的逻辑,就出现了循环调用。当然这样也是一个方法,适合复杂度不高的APP。
回归整体,还是得用dialog。那么怎么解决单例的问题呢?其实我们可以参考单例的思想,做一个伪单例出来。当我们调用这个dialog的时候就创建出来,dismiss的时候就销毁这个dialog对象。再结合基类。这是目前为止我能力所及的方法。
好,废话不多说,撸代码!!
public class NetWaitDialogUtils {
private static NetWaitDialogUtils instance;
private static Context context;
public NetWaitDialog netWaitDialog;
private NetWaitDialogUtils() {
}
public static NetWaitDialogUtils getInstance(Context mcontext) {
context = mcontext;
if (instance == null) {
instance = new NetWaitDialogUtils();
}
return instance;
}
public void show(){
Log.d("网络加载", "NetWaitDialogUtils.context:" + this.context);
if (netWaitDialog!=null){
if (!netWaitDialog.isShowing()){
Log.d("网络加载", "show");
try {
netWaitDialog.show();
}catch (Exception e){
Log.d("网络加载", "网络加载异常原因 --> "+e);
}
}
}else {
Log.d("网络加载", "new NetWaitDialog");
netWaitDialog = new NetWaitDialog(context, R.style.netwait_dialog);
Log.d("网络加载", "新建netWaitDialog,调用show");
try {
netWaitDialog.show();
}catch (Exception e){
Log.d("网络加载", "网络加载异常原因 --> "+e);
}
}
}
public void dismiss(){
if (netWaitDialog!=null)
if (netWaitDialog.isShowing()){
Log.d("网络加载", "dismiss");
netWaitDialog.dismiss();
}
Log.d("网络加载", "null");
netWaitDialog = null;
}
}
<!-- 网络加载dialog样式 -->
<style name="netwait_dialog" parent="@android:style/Theme.Dialog">
<item name="android:windowIsFloating">true</item> <!--是否浮在界面上-->
<item name="android:windowBackground">@android:color/transparent</item> <!--窗口背景色透明-->
<item name="android:backgroundDimEnabled">false</item> <!--背景是否模糊显示-->
</style>
/**
* Created by HXY on 2018/10/23.
* Be used for : 网络加载状态提示弹窗
*/
public class NetWaitDialog extends AlertDialog {
private Context context;
private SimpleDraweeView netwait_dialog_gif;
public NetWaitDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
initView(context);
}
/**
* 初始化
*/
private void initView(Context mcontext) {
context = mcontext;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置dialog显示的位置为居中
Window window = getWindow();
window.setGravity(Gravity.CENTER);
//添加布局
setContentView(R.layout.netwait_dialog);
//点击外部消失
setCanceledOnTouchOutside(false);
netwait_dialog_gif = (SimpleDraweeView) findViewById(R.id.netwait_dialog_gif);
//展示动图
DraweeController draweeController_phone_wait = Fresco.newDraweeControllerBuilder()
.setAutoPlayAnimations(true)
//设置uri,加载本地的gif资源
.setUri(Uri.parse("res://"+context.getPackageName()+"/"+R.drawable.wait))
.build();
netwait_dialog_gif.setController(draweeController_phone_wait);
}
}
layout布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:fresco="http://schemas.android.com/apk/res-auto">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/netwait_dialog_gif"
android:layout_width="360dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
fresco:roundedCornerRadius="20dp"></com.facebook.drawee.view.SimpleDraweeView>
</RelativeLayout>
这里我用的是Fresco图片框架,附上
//fresco
implementation 'com.facebook.fresco:fresco:1.5.0'
本地GIF资源的话替换成自己的就行了。这里提供一下我暂时用的。