现在的位置: 首页 > 综合 > 正文

Android学习札记38:关于安全退出已创建多个Activity的应用(1)

2018年04月04日 ⁄ 综合 ⁄ 共 2217字 ⁄ 字号 评论关闭

最初看到这个问题,是在一道面试题上。 

不同与其他面试题,我觉得这道题很具有实际意义。所以先实际操作下,解决这个问题。 

在此,我也啰嗦一下,大概说说解决这个问题的几种方案: 


1、借助系统的 API 

首先,2.2 以前和 2.2 以后采用的方法是不同的。但都是针对系统级别的东西进行操作。从进程和包的角度来达到此效果。 

所以需要添加授权,但是遗憾的是,这些方法涉及底层,而且在我们的应用中是起不到效果的。 

这个方案被我排除了。 


2、抛出异常,Force Close 

这个我觉得很不靠谱。这确实能一下子退出应用。 

但是,其一:不能保证所有的 Activity 都被 finish;其二:Force Close 的窗口,这个是很糟糕的,当然可以重写一些方法,使不弹出这个窗口。 

这个方案也被我排除了。 


3、递归退出 

使用 startActivityForResult() 打开新的 Activity,并加上标识。 

在onActivityResult() 中进行处理,递归关闭。 

这个方式我不是很清楚其具体做法,感觉有些复杂。 


4、发送特定广播 

这个办法是我最赞同的,但是实际操作起来确遇到了问题。 

首先看 onReceive(Context context, Intent intent)方法, 可以通过 context 取得ActivityManager,之后取得当前运行的 task 的信息,看起来离成功不远了。 

Activity 是被组织在 task 中的,获得了 task 信息,那是不是就可以取得其中的 Activity 实例? 

// 通过 context 获取系统服务,得到 ActivityManager   
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);  
// 获取当前运行中的 TaskInfo    
// 获取的是一个 List 集合,也就是说当前系统中的 task 有多个,在我测试代码中有 2 个  
// 关于该方法的参数,我从源码看了下,是指返回集合的最大可能条目数,实际返回数可能  
// 小于这个数目,取决于用户启动了几个 task  
List<ActivityManager.RunningTaskInfo> tasks = manager.getRunningTasks(10); 

包含 task 信息的是一个 ActivityManager 的静态内部类,RunningTaskInfo。 

不过从中能取得的信息有限:

// task 栈底的 Activity  
ComponentName baseActivity = task.baseActivity;  
// task 栈顶的 Activity
ComponentName topActivity = task.topActivity;

这就有两个问题, 

其一,无法取得 task 中的每一个 Activity 

其二,不能取得 Activity 的实例 

我的研究到此止步,希望有达人能为我解惑。


5、记录每一个创建的 Activity,这也是我最后采用的方法。 

为入口 Activity 添加一个静态的 List<Activity>, 

之后,每一个 Activiity 的 onCreate() 方法中,将自身加入这个 List, 

当程序退出时,遍历这个 List,执行 finish()方法

for (Activity act : MainActivity.tasks) {
	if ( !act.isFinishing()) {
		act.finish();
	}
}  
MainActivity.tasks = null;

测试了一下,能达到效果。 

但是还是有一点担心,这就是 Activity 成员变量的生命周期问题, 

当该成员变量的生命周期大于 Activity 的生命周期,就有可能造成内存泄露。 

不知这样的解决方案有没有这个问题。请高手指教。


利用 Application 实现:

public class MyApp extends Application {
	private List<Activity> mainActivity = new ArrayList<Activity>();

	public List<Activity> MainActivity () {
		return mainActivity; 
	}

	public void addActivity(Activity act) {
		mainActivity.add(act);
	}

	public void finishAll() {
		for (Activity act : mainActivity.tasks) {
			if (!act.isFinishing()) {
				act.finish();
			}
		}

		MainActivity.tasks = null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		setState(we);
		MyApp appState = (MyApp)getApplicationContext();
		appState.addActivity(this)
	} 
}

结束代码 

MyApp appState = (MyApp)getApplicationContext(); 
appState .finishAll() 

代码随手写的,没调试,参考而已 

别忘了在 manifest 中的 application 标签中添加 android:name=".MyApp"


转载自:

http://lagunarock.iteye.com/blog/1054384





抱歉!评论已关闭.