国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android單一實例全局可調用網絡加載彈窗

2019-10-21 21:34:02
字體:
來源:轉載
供稿:網友

最近因為項目需求,需要完成一個全局的網絡加載彈窗需求,真正完成這個需求之后,感覺最重要的不是結果,而是思維。

我剛開始接到這個需求的時候,第一種想到的方案是 基類加單例。但是實際做起來之后發現,因為單例的原因,你的彈窗只能在第一次創建這個單例的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();   }   } }}

布局文件:

<?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.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>

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 荔波县| 莫力| 鹤壁市| 汝阳县| 德州市| 老河口市| 吉木乃县| 贡嘎县| 炎陵县| 通化市| 三河市| 双峰县| 祥云县| 工布江达县| 乐东| 奉新县| 常熟市| 开平市| 梅河口市| 义乌市| 和田市| 营山县| 罗田县| 临清市| 探索| 平昌县| 肥乡县| 上思县| 固原市| 青冈县| 贵溪市| 佛冈县| 冷水江市| 永兴县| 万宁市| 牡丹江市| 邵阳市| 灵山县| 萨迦县| 兰州市| 布尔津县|