Recently, due to project requirements, a global network loading pop-up requirement needs need to be completed. After truly completing this requirement, I feel that the most important thing is not the result, but the thinking.
When I first received this requirement, the first solution I thought of was base class plus singleton. But after actually doing it, it is found that because of the singleton, your pop-up window can only be displayed in the activity of the first time that this singleton was created.
So after discovering this problem, I will improve it on this basis. What if I don’t use the context of activity, but use a global context similar to Application? Of course, personal abilities are limited, so this idea was destroyed. Later, the instructor guided him and used the service context to set the dialog style to a system-level pop-up window. Then there will be a potential situation. If the APP retreats to the background, no matter which page the user is on when loading the network, this pop-up window will be displayed, which seriously affects the user experience.
Later, I returned to the starting point and needed to implement two points, one: global callable. Two: Single instance.
Let's summarize the problems encountered:
1. Dialog must rely on activity
2. Because of singleton, dialog can only be displayed on the first time the activity of singleton is created.
3. System-level pop-up window cannot be used
OK, based on these questions and requirements, combined with the knowledge you have mastered.
The dialog must rely on activity, so I will create an activity to specifically host the dialog. The activity background is set to transparent and the effect is achieved.
At this time, new problems will arise. If you open this activity in a singleton, there will be many dialog objects, which will violate the original intention. If you create a dialog in a singleton, there will be many intent objects when you open the activity, which will not be worth the loss. Workaround: Create two singletons to ensure that both the intent object and the dialog object remain unique.
In actual tests, it was found that the first time it could be displayed normally, but the second time it would crash.
reason:When the activity is destroyed and recreated, the context changes. Because of singleton, the context of your dialog is the context when the activity was created for the first time. Then when you call this dialog again, an exception that does not exist in the activity will be reported.
There seems to be no solution here.
When I thought about this question again, a sudden flash of inspiration was. Why did I have to use dialog? Since I have created an activity that specifically hosts this dialog, and the life and death of the activity is completely consistent with the dialog, why should I create another dialog? Isn't it okay to directly write the layout of the dialog in activity? When the external creates this activity, the animation is directly played, and a closing method is provided to the external. Moreover, singletons can be used to ensure the singleness of this activity instance.
Do it when you think of it, and after trying and optimizing, the problem is solved perfectly.
The following is the specific implementation code:
Activity to display:
public class NetWaitDialogActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(.activity_net_wait_dialog); //Add Activity instance to AppManager's stack ().addActivity(this); Transparentstatusbar(); SimpleDraweeView netwait_dialog_gif = (SimpleDraweeView) findViewById(.netwait_dialog_gif); //Display animation DraweeController draweeController_phone_wait = () .setAutoPlayAnimations(true) //Set URI and load local gif resources .setUri(("res://"+()+"/"+)) .build(); netwait_dialog_gif.setController(draweeController_phone_wait); } /** * Transparent status bar */ private void Transparentstatusbar() { ViewGroup contentFrameLayout = (ViewGroup) findViewById(Window.ID_ANDROID_CONTENT); View parentView = (0); if (parentView != null && .SDK_INT >= 14) { (true); getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); } } @Override protected void onDestroy() { (); ("Network Loading Popup", ""); } public static void dismiss(){ ("Network Loading Popup", "Calldismiss()method"); if (().isActivityExist()){ //End the activity of the specified class name ("Network Loading Popup", "Calling Activity Management Tool to End Activity"); ().finishActivity(); } else { ("Network Loading Popup", "The specified class does not exist, call the alternate method"); if (((Activity)NetWaitDialogContext).isFinishing() || ((Activity)NetWaitDialogContext).isDestroyed()) { ("Network Loading Popup", "The Internet pop-up window does not exist"); } else { ("Network Loading Popup", "Call forcing close"); ((Activity)NetWaitDialogContext).finish(); } } } }
Layout file:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:andro android:layout_width="match_parent" android:layout_height="match_parent" xmlns:fresco="/apk/res-auto"> < android: android:layout_width="360dp" android:layout_height="100dp" android:layout_centerInParent="true" fresco:roundedCornerRadius="20dp"></> </RelativeLayout>
Create transparent styles in:
<!-- Network loadingactivitybackground --> <style name="Transparent" parent=""> <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>
Set styles in:
<activity android:name=".NetWaitDialogActivity" android:theme="@style/Transparent"></activity>
Singleton tool class:
public class NetWaitStatusUtils { private static NetWaitStatusUtils instance; private Intent intent; private Context context; private NetWaitStatusUtils(Context context) { = context; intent = new Intent(context, ); } public static NetWaitStatusUtils getInstance(Context context) { if (instance == null) { instance = new NetWaitStatusUtils(context); } return instance; } public void show(){ (intent); } public void dismiss(){ (); } }
Get the instance in the base class:
netWaitDialog = (getApplication());
External call:
public class MainActivity extends IActivity { private Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); Button load = findViewById(); Button gotwo = findViewById(); (new () { @Override public void onClick(View v) { (); (new Runnable(){ @Override public void run() { (); } }, 3000); } }); (new () { @Override public void onClick(View v) { startActivity(new Intent(,)); finish(); } }); } @Override protected int getLayoutId() { return .activity_main; } }
There is another thing to note here, which is the startup mode of activity, and it is recommended to use singletask. But this also has a disadvantage, that is, it will destroy all activity instances from it to the top of the stack. You can Baidu on your own.
Here I am using an activity management class:
package .; import ; import ; import ; import ; import ; import ; import ; /** * Created by HXY on 18-12-1. */ public class MyActivityManager { private static Stack<Activity> activityStack; private static MyActivityManager instance; private MyActivityManager(){} /** * Single instance */ public static MyActivityManager getAppManager(){ if(instance==null){ instance=new MyActivityManager(); } return instance; } /** * Add Activity to the Stack */ public void addActivity(Activity activity){ if(activityStack==null){ activityStack=new Stack<Activity>(); } (activity); ("MyActivityManager", ()); } /** * Get the current activity (last pressed in the stack) */ public Activity currentActivity(){ Activity activity=(); return activity; } /** * End the current activity (last pressed in the stack) */ public void finishActivity(){ Activity activity=(); if(activity!=null){ (); activity=null; } } /** * End the specified activity */ public void finishActivity(Activity activity){ if(activity!=null){ (activity); (); activity=null; } } /** * End the activity of the specified class name */ public void finishActivity(Class<?> cls){ // try { for (Activity activity : activityStack) { if(().equals(cls) ){ finishActivity(activity); } } // }catch (Exception e){ // ("MyActivityManager", "The specified class does not exist");// } } /** * Determine whether an activity exists * * @param clz * @return */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public boolean isActivityExist(Class<?> clz) { boolean res; Activity activity = getActivity(clz); if (activity!=null) ("MyActivityManager", "A Activity instance that determines whether it exists --> "+()); if (activity == null) { res = false; } else { if (() || ()) { res = false; } else { res = true; } } ("MyActivityManager", "Specify the Activity Existence Status" + res); return res; } /** * Get the specified activity instance * * @param clazz Activity class object * @return */ public Activity getActivity(Class<?> clazz) { Activity returnActivity = null; for (Activity activity : activityStack) { if(().equals(clazz) ){ returnActivity = activity; return returnActivity; } } return null; } /** * End all activities */ public void finishAllActivity(){ for (int i = 0, size = (); i < size; i++){ if (null != (i)){ (i).finish(); } } (); } /** * Exit the application */ public void AppExit(Context context) { try { finishAllActivity(); ActivityManager activityMgr= (ActivityManager) (Context.ACTIVITY_SERVICE); (()); (0); } catch (Exception e) { (); } } }
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.