Android加载弹窗,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();

}

}

}

}

布局文件:

android:layout_width="match_parent"

android:layout_height="match_parent"

xmlns:fresco="http://schemas.android.com/apk/res-auto">

android:id="@+id/netwait_dialog_gif"

android:layout_width="360dp"

android:layout_height="100dp"

android:layout_centerInParent="true"

fresco:roundedCornerRadius="20dp">

style.xml中创建透明样式:

@android:color/transparent

true

@android:style/Animation

true

AndroidManifest.xml中设置样式:

android:theme="@style/Transparent">

单例工具类:

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 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();

}

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();

}

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值