Android单一实例全局可调用网络加载弹窗

发布时间:2019-08-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Android单一实例全局可调用网络加载弹窗脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

最近因为项目需求,需要完成一个全局的网络加载弹窗需求,真正完成这个需求之后,感觉最重要的不是结果,而是思维

我刚开始接到这个需求的时候,第一种想到的方案是 基类加单例。但是实际做起来之后发现,因为单例的原因,你的弹窗只能在第一次创建这个单例的activITy中显示出来。

那么发现这个问题之后在这个的基础上改进一下,如果我不用activity的上下文,而是采用类似于Application的一种全局上下文呢?当然,个人能力有限,这种想法就给毙掉了,后来由导师指点,利用service的上下文,diaLOG的style设置为系统级弹窗,那么这时候就会有一种潜在的情况,如果APP退到后台的话,加载网络的时候不管用户在那个页面,都会显示这个弹窗,严重影响用户体验。

后来把思路又回到起点,需要实现两个点,一:全局可调用。二:单一实例。

总结一下遇到的问题:

一、dialog必须依赖activity

二、因为单例的原因,dialog只能在第一次创建单例的activity显示

三、不能使用系统级弹窗

OK,基于这些问题和要求,结合自己所掌握的知识。

dialog必须依赖activity,那我就创建一个activity,专门去承载这个dialog,activity背景设置为透明,效果达到。

这时又会出现新的问题,如果在单例中去开启这个activity,那么就会有很多dialog对象,违反初衷,如果在单例中创建dialog,那么开启activity的时候又会有很多intent对象,得不偿失。解决方法,创建两个单例,保证intent对象和dialog对象都保持唯一。

实际测试发现,第一次可以正常显示,第二次就会崩溃

原因:当activity被销毁,又重新创建的时候,上下文会改变。因为单例的原因,你dialog的上下文还是第一次activity被创建时候的上下文,那么你再次调用这个dialog的时候,就会报activity不存在的异常。

到这里似乎没有办法解决了。

再次思考这个问题,突然灵光一闪,为什么我非要用dialog呢?我既然已经创建出一个专门承载这个dialog的activity了,而且activity的死活是完全和dialog一致的,那么我为什么还要再去创建一个dialog呢?直接把dialog的布局写在activity里不行吗?当外部去创建这个activity的时候直接播放动画,同时提供一个暴露给外部的关闭方法。而且这样也能用单例保证这个activity实例的单一性。

想到就去做,经过尝试和优化,问题完美解决。

下面是具体实现代码:

要显示的activity:

 public class NetWaitDialogActivity extends AppCompatActivity {    @override  PRotected void onCreate(Bundle savedInstancestate) {   suPEr.onCreate(savedInstanceState);   setContentView(R.layout.activity_net_wait_dialog);   //将Activity实例添加到AppManager的堆栈   MyActivityManager.getAppManager().addActivity(this);     Transparentstatusbar();     SimpleDraweeView netwait_dialog_gif = (SimpleDraweeView) findViewById(R.id.netwait_dialog_gif);   //展示动图   DraweeController draweeController_phone_wait = Fresco.newDraweeControllerBuilder()     .setAutoplayAnimations(true)     //设置uri,加载本地的gif资     .setUri(Uri.parse("res://"+this.getPackageName()+"/"+R.drawable.wait))     .build();   netwait_dialog_gif.setController(draweeController_phone_wait);  }    /**   * 透明状态栏   */  private void Transparentstatusbar() {   ViewGroup contentFrameLayout = (ViewGroup) findViewById(Window.ID_ANDROID_CONTENT);   View parentView = contentFrameLayout.getChildAt(0);   if (parentView != null && Build.VERSION.SDK_INT >= 14) {    parentView.setFitsSystemWindows(true);    getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);   }  }    @Override  protected void onDestroy() {   super.onDestroy();   Log.d("网络加载弹窗", "NetWaitDialogActivity.onDestroy");  }    public static void dismiss(){   Log.d("网络加载弹窗", "调用dismiss()方法");   if (MyActivityManager.getAppManager().isActivityExist(NetWaitDialogActivity.class)){    //结束指定类名的Activity    Log.d("网络加载弹窗", "调用Activity管理工具结束Activity");    MyActivityManager.getAppManager().finishActivity(NetWaitDialogActivity.class);   }   else {    Log.d("网络加载弹窗", "指定类不存在,调用备用方法");    if (((Activity)NetWaitDialogContext).isFinishing() || ((Activity)NetWaitDialogContext).isDestroyed()) {     Log.d("网络加载弹窗", "网络加弹窗不存在");    } else {     Log.d("网络加载弹窗", "调用强制关闭");     ((Activity)NetWaitDialogContext).finish();    }     }  } }

布局文件:

 <&#63;XMl version="1.0" encoding="utf-8"?> <RelativeLayout xMLns:android="http://schemas.android.COM/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  xmlns:fresco="http://schemas.android.com/apk/res-auto">      <com.face@R_360_2396@.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>

style.xml中创建透明样式:

 <!-- 网络加载activity背景 -->  <style name="Transparent" parent="Theme.AppCompat.Light.NoActionBar">   <item name="android:windowBackground">@android:color/transparent</item>   <item name="android:windowIsTranslucent">true</item>   <item name="android:windowAnimationStyle">@android:style/Animation</item>   <item name="android:windowNoTitle">true</item>  </style>

AndroidManifest.xml中设置样式

 <activity android:name=".NetWaitDialogActivity"    android:theme="@style/Transparent"></activity>

单例工具类:

 public class NetWaitStatusUtils {  private static NetWaitStatusUtils instance;  private Intent intent;  private Context context;    private NetWaitStatusUtils(Context context) {   this.context = context;   intent = new Intent(context, NetWaitDialogActivity.class);  }    public static NetWaitStatusUtils getInstance(Context context) {   if (instance == null) {    instance = new NetWaitStatusUtils(context);   }   return instance;  }    public void show(){   context.startActivity(intent);  }    public void dismiss(){   NetWaitDialogActivity.dismiss();  } }

在基类中获取实例:

 netWaitDialog = NetWaitStatusUtils.getInstance(getApplication());

外部调用:

 public class MainActivity extends IActivity {    private Handler handler = new Handler();    @Override  protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   Button load = findViewById(R.id.load);   Button gotwo = findViewById(R.id.gotwo);   load.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View v) {     netWaitDialog.show();     handler.postDelayed(new Runnable(){      @Override      public void run() {       netWaitDialog.dismiss();      }     }, 3000);    }   });   gotwo.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View v) {     startActivity(new Intent(MainActivity.this,Main2Activity.class));     finish();    }   });  }    @Override  protected int getLayoutId() {   return R.layout.activity_main;  }     }

这里还有一点需要注意,就是activity的启动模式,推荐使用singletask。但是这样也会有一个弊端,就是它会把自它到栈顶的所有activity实例都销毁,具体大家可以自行百度

我这里是用到一个activity的管理类:

 package com.example.a9focus.sxt.base;   import android.annotation.TargetApi; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; import android.os.Build; import android.util.Log;   import java.util.Stack;   /**  * Created by HXY on 18-12-1.  */   public class MyActivityManager {  private static Stack<Activity> activityStack;  private static MyActivityManager instance;    private MyActivityManager(){}  /**   * 单一实例   */  public static MyActivityManager getAppManager(){   if(instance==null){    instance=new MyActivityManager();   }   return instance;  }  /**   * 添加Activity到堆栈   */  public void addActivity(Activity activity){   if(activityStack==null){    activityStack=new Stack<Activity>();   }   activityStack.add(activity);   Log.d("MyActivityManager", activityStack.toString());  }  /**   * 获取当前Activity(堆栈中最后一个压入的)   */  public Activity currentActivity(){   Activity activity=activityStack.lastElement();   return activity;  }  /**   * 结束当前Activity(堆栈中最后一个压入的)   */  public void finishActivity(){   Activity activity=activityStack.lastElement();   if(activity!=null){    activity.finish();    activity=null;   }  }  /**   * 结束指定的Activity   */  public void finishActivity(Activity activity){   if(activity!=null){    activityStack.remove(activity);    activity.finish();    activity=null;   }  }  /**   * 结束指定类名的Activity   */  public void finishActivity(Class<?> cls){ //  try {    for (Activity activity : activityStack) {     if(activity.getClass().equals(cls) ){      finishActivity(activity);     }    } //  }catch (Exception e){ //   Log.d("MyActivityManager", "指定类不存在"); //  }    }    /**   * 判断一个Activity 是否存在   *   * @param clz   * @return   */  @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)  public boolean isActivityExist(Class<?> clz) {   boolean res;   Activity activity = getActivity(clz);   if (activity!=null)    Log.d("MyActivityManager", "判断是否存在的Activity实例 --> "+activity.toString());   if (activity == null) {    res = false;   } else {    if (activity.isFinishing() || activity.isDestroyed()) {     res = false;    } else {     res = true;    }   }   Log.d("MyActivityManager", "指定Activity存在状态" + res);   return res;  }    /**   * 获得指定activity实例   *   * @param clazz Activity 的类对象   * @return   */  public Activity getActivity(Class<?> clazz) {   Activity returnActivity = null;   for (Activity activity : activityStack) {    if(activity.getClass().equals(clazz) ){     returnActivity = activity;     return returnActivity;    }   }   return null;  }    /**   * 结束所有Activity   */  public void finishAllActivity(){   for (int i = 0, size = activityStack.size(); i < size; i++){    if (null != activityStack.get(i)){     activityStack.get(i).finish();    }   }   activityStack.clear();  }  /**   * 退出应用程序   */  public void AppExit(Context context) {   try {    finishAllActivity();    ActivityManager activityMgr= (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);    activityMgr.restartPackage(context.getPackageName());    System.exit(0);   } catch (Exception e) {    e.printStackTrace();   }  } }
android教程
脚本网站
android studio

脚本宝典总结

以上是脚本宝典为你收集整理的Android单一实例全局可调用网络加载弹窗全部内容,希望文章能够帮你解决Android单一实例全局可调用网络加载弹窗所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。