上家公司由于某些缘由离职了,因而天天出去面试也没时间来写个人博客了,这两天结束了十来天的动荡,算是稳定下来了,又从新拾起纸笔,写上两笔。java
看公司代码的时候就在想,一个维护了两年的项目势必是有他独特的地方的,因而乎,在不少小细节的地方,之前虽然也面试准备过,但是确实没写过。这些东西,可能看起来不起眼,平时没什么用,可能在某些时候避免了程序崩溃的危险呢。android
好比,今天就实践一个退出不少Activity的功能,在某些状况下保证安全。面试
借鉴一篇博客中的例子吧:(注册流程)c#
若是一个交互流程中,是从A开始,按照A - B - C - D - A这样的顺序进行的话,那么B,C,D这3个活动界面会根据你D中最后的操做来进行保留或是摧毁,例如安全
(1)注册流程中,在A界面点击注册,经过B,C,D界面完成注册后,B,C,D就随之摧毁,而若是D中注册不成功没跳转会A的话,那么B,C,D就不能摧毁,以前所填的内容也必须保留。微信
(2)客户端交互中,返回首页按钮,因为在频繁的点击打开过多的界面(如微信查看朋友圈),返回首页就必须一个一个back回去,全部有的客户端为了优化用户体验,便会加入一个按钮返回首页(以前打开的所有关闭)。ide
以上例子都涉及到了 --- 如何安全退出多个ACTIVITY 这个问题。优化
其实,这个问题的解决方案有好多种,而且各有各的优缺点,下面就罗列出多个方案以及各个方案的优缺点所在,以及本人所在项目采用的方案。this
android.os.Process.killProcess(android.os.Process.myPid()) //获取PID System.exit(0); //常规java、c#的标准退出法,返回值为0表明正常退出spa
首先要说明该方法运行在Android 1.5 API Level为3以上才能够,同时须要权限
ActivityManager am = (ActivityManager)getSystemService (Context.ACTIVITY_SERVICE);
am.restartPackage(getPackageName());复制代码
系统会将,该包下的 ,全部进程,服务,所有杀掉,就能够杀干净了,要注意加上
<uses-permission android:name=\"android.permission.RESTART_PACKAGES\"></uses-permission>复制代码
思路:经过Intent的Flags来控制堆栈去解决 android中,每打开一个Activity,便会在栈中加入一个Activity,当该Activity被摧毁后,栈中便移除了它,而且栈中的Activity是按照开打的前后顺序依次排排列的。 Android的窗口类提供了历史栈,咱们能够经过stack的原理来巧妙的实现,这里咱们在A窗口打开B窗口时在Intent中直接加入标 志 Intent.FLAG_ACTIVITY_CLEAR_TOP,这样开启B时将会清除该进程空间的全部Activity。
btn_finish.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(INTENT_METHOD_FIRST_SINGUP);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});复制代码
其中的 INTENT_METHOD_FIRST_SINGUP 是登陆界面的Intent隐式Action。
优缺点: 优:使用对栈的巧妙利用,不会形成内存无端占用等问题
public class ScreenManager {
private static Stack<Activity> activityStack;
private static ScreenManager instance;
private ScreenManager(){
}
public static ScreenManager getScreenManager(){
if(instance==null){
instance=new ScreenManager();
}
return instance;
}
//退出栈顶Activity
public void popActivity(Activity activity){
if(activity!=null){
activity.finish();
activityStack.remove(activity);
activity=null;
}
}
//得到当前栈顶Activity
public Activity currentActivity(){
Activity activity=activityStack.lastElement();
return activity;
}
//将当前Activity推入栈中
public void pushActivity(Activity activity){
if(activityStack==null){
activityStack=new Stack<Activity>();
}
activityStack.add(activity);
}
//退出栈中全部Activity
public void popAllActivityExceptOne(Class cls){
while(true){
Activity activity=currentActivity();
if(activity==null){
break;
}
if(activity.getClass().equals(cls) ){
break;
}
popActivity(activity);
}
}
}复制代码
思路:经过在Application中用一个列表来记录当前所打开的Activity,根据需求去遍历finish()。
public class AppApplication extends Application {
private static AppApplication mAppApplication;
/** 当前打开的activity列表 */
public ArrayList<Activity> activityList;
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
mAppApplication = this;
}
/** 获取Application */
public static AppApplication getApp() {
if (mAppApplication == null) {
mAppApplication = new AppApplication();
}
return mAppApplication;
}
/** 添加当前Activity 到列表中 */
public void addActivity(Activity acitivity) {
if(activityList == null){
activityList = new ArrayList<Activity>();
}
activityList.add(acitivity);
}
/** 清空列表,取消引用*/
public void clearActivity(){
activityList.clear();
}
/** 遍历退出全部Activity */
public void exit() {
for (Activity activity : activityList) {
activity.finish();
}
clearActivity();//千万记得清空取消引用。
System.exit(0);
}复制代码
优缺点: 缺:若是处理不当,容易形成不在当前界面的Activity被全局引用而摧毁不掉,内存得不到释放,从而无端占用没必要要的内存。
经过Activity建立的时候,设置监听广播,在注册流程最后步完成注册时候,发送广播进行遍历finish().
代码:
/** * 初始化退出广播 */
public void initFinishReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(INIENT_FINISH);
registerReceiver(mFinishReceiver, filter);
}
/** * 监听是否退出的广播 */
public BroadcastReceiver mFinishReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (INIENT_FINISH.equals(intent.getAction())) {
finish();
}
}
};
在流程中的每步Activity中,初始化广播,以后在点击完成注册时候,发送广播
[java] view plain copy 在CODE上查看代码片派生到个人代码片
btn_finish.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
getApplicationContext().sendBroadcast(new Intent(INIENT_FINISH));
}
});
缺:开启过多的广播监听,以为会浪费资源。复制代码
我这边采用第三种方法,以下
public void exit() {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setClass(this, HomePageActivity.class);
intent.putExtra("exitApp", true);
Misc.startActivity(intent);
}复制代码