转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0629/8124.html
前言
最近项目中涉及需要在一个Activity中关闭另一个Activity或者在一个Activity中关闭多个Activity的需求,不涉及到应用的退出。自己首先想了一些方案,同时也查了一些方案,就各个方案比较下优劣。
方案一:广播
这个是最容易想到的,同时也是网上提供最多的。 由于多个Activity要使用,关闭页面的广播最好写在基类BaseActivity中,也可以在各个子页面单独写,但是代码量就增加了。
-
public class BaseActivity extends Activity {
-
//根据需求定义自己需要关闭页面的action
-
public static final String RECEIVER_ACTION_FINISH_A = "receiver_action_finish_a";
-
public static final String RECEIVER_ACTION_FINISH_B = "receiver_action_finish_b";
-
public static final String RECEIVER_ACTION_FINISH_C = "receiver_action_finish_c";
-
public static final String RECEIVER_ACTION_FINISH_D = "receiver_action_finish_d";
-
private FinishActivityRecevier mRecevier;
-
@Override
-
protected void onCreate(@Nullable Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
mRecevier = new FinishActivityRecevier();
-
registerFinishReciver();
-
}
-
private void registerFinishReciver() {
-
IntentFilter intentFilter = new IntentFilter();
-
intentFilter.addAction(RECEIVER_ACTION_FINISH_A);
-
intentFilter.addAction(RECEIVER_ACTION_FINISH_B);
-
intentFilter.addAction(RECEIVER_ACTION_FINISH_C);
-
intentFilter.addAction(RECEIVER_ACTION_FINISH_D);
-
registerReceiver(mRecevier, intentFilter);
-
}
-
private class FinishActivityRecevier extends BroadcastReceiver {
-
@Override
-
public void onReceive(Context context, Intent intent) {
-
//根据需求添加自己需要关闭页面的action
-
if (RECEIVER_ACTION_FINISH_A.equals(intent.getAction()) ||
-
RECEIVER_ACTION_FINISH_B.equals(intent.getAction()) ||
-
RECEIVER_ACTION_FINISH_C.equals(intent.getAction()) ||
-
RECEIVER_ACTION_FINISH_D.equals(intent.getAction())) {
-
BaseActivity.this.finish();
-
}
-
}
-
}
-
@Override
-
protected void onDestroy() {
-
if (mRecevier != null) {
-
unregisterReceiver(mRecevier);
-
}
-
super.onDestroy();
-
}
-
}
发送广播就需要在各个需求子Activity中进行了,这里使用工具类,方便以后多次或者拓展使用,只需要在需求子Activity中直接调用就行。
-
public class BroadcastUtils {
-
/**
-
* 发送finish页面的广播
-
* action可以自己根据需要添加
-
* @param context
-
*/
-
public static void sendFinishActivityBroadcast(Context context) {
-
Intent intent = new Intent(BaseActivity.RECEIVER_ACTION_FINISH_B);
-
context.sendBroadcast(intent);
-
intent = new Intent(BaseActivity.RECEIVER_ACTION_FINISH_C);
-
context.sendBroadcast(intent);
-
}
-
}
优劣: 有点:最常规使用,不会出现内存泄漏,在基类中操作,代码量不多。 缺点:项目中若是需要关闭页面多的话,需要发送大量广播,会降低性能。
方案二:static activity
-
private static AActivity sInstance;
-
public static AActivity getInstance() {
-
if (sInstance != null) {
-
return sInstance;
-
}
-
return null;
-
}
-
public static void finishActivity() {
-
if (sInstance != null) {
-
sInstance.finish();
-
}
-
}
缺点明显:内存泄漏。可以改进为弱引用
-
public class BActivity extends BaseActivity {
-
private static WeakReference<BActivity> sActivityRef;
-
public static void finishActivity() {
-
if (sActivityRef != null && sActivityRef.get() != null) {
-
sActivityRef.get().finish();
-
}
-
}
-
@Override
-
protected void onCreate(@Nullable Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_b);
-
sActivityRef = new WeakReference<>(this);
-
Button btnB = (Button) findViewById(R.id.btn_b);
-
btnB.setOnClickListener(new View.OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
startActivity(new Intent(BActivity.this, CActivity.class));
-
}
-
});
-
}
-
}
纠结点在于,WeakReference被static之后,里面包裹的引用会被影响吗?查了一下WeakReference以及JVM相关,虽然WeakReference被static了,生命周期变长了,但是WeakReference关联的对象不受影响的,依然遵循WeakReference在gc时候的规则。
优劣: 优点:代码简单直观,引入WeakReference,解决了内存泄漏问题。 缺点:在每个activity中都要添加,代码量多。
方案三:集合或栈
-
public class FinishActivityManager extends BaseActivity {
-
private FinishActivityManager() {
-
}
-
private static FinishActivityManager sManager;
-
private List<Activity> activityList;
-
public static FinishActivityManager getManager() {
-
if (sManager == null) {
-
synchronized (FinishActivityManager.class) {
-
if (sManager == null) {
-
sManager = new FinishActivityManager();
-
}
-
}
-
}
-
return sManager;
-
}
-
/**
-
* 添加Activity到集合中
-
*/
-
public void addActivity(Activity activity) {
-
if (activityList == null) {
-
activityList = new LinkedList<>();
-
}
-
activityList.add(activity);
-
}
-
/**
-
* 关闭指定的Activity
-
*/
-
public void finishActivity(Activity activity) {
-
if (activityList != null && activity != null && activityList.contains(activity)) {
-
//使用迭代器安全删除
-
for (Iterator<Activity> it = activityList.iterator(); it.hasNext(); ) {
-
Activity temp = it.next();
-
// 清理掉已经释放的activity
-
if (temp == null) {
-
it.remove();
-
continue;
-
}
-
if (temp == activity) {
-
it.remove();
-
}
-
}
-
activity.finish();
-
}
-
}
-
/**
-
* 关闭指定类名的Activity
-
*/
-
public void finishActivity(Class<?> cls) {
-
if (activityList != null) {
-
// 使用迭代器安全删除
-
for (Iterator<Activity> it = activityList.iterator(); it.hasNext(); ) {
-
Activity activity = it.next();
-
// 清理掉已经释放的activity
-
if (activity == null) {
-
it.remove();
-
continue;
-
}
-
if (activity.getClass().equals(cls)) {
-
it.remove();
-
activity.finish();
-
}
-
}
-
}
-
}
-
/**
-
* 关闭所有的Activity
-
*/
-
public void finishAllActivity() {
-
if (activityList != null) {
-
for (Iterator<Activity> it = activityList.iterator(); it.hasNext(); ) {
-
Activity activity = it.next();
-
if (activity != null) {
-
activity.finish();
-
}
-
}
-
activityList.clear();
-
}
-
}
-
/**
-
* 退出应用程序
-
*/
-
public void exitApp() {
-
try {
-
finishAllActivity();
-
// 退出JVM,释放所占内存资源,0表示正常退出
-
System.exit(0);
-
// 从系统中kill掉应用程序
-
android.os.Process.killProcess(android.os.Process.myPid());
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}
这种方式网上很多,但注意在删除的时候使用迭代器,否则会出现并发修改异常。应用中要是不使用这种封装的方式去finish掉Activity的时候,封装的manager并不知道,没有断开并释放掉其引用,会引起内存泄漏。继续用WeakReference改进。
-
public class FinishActivityManager extends BaseActivity {
-
private FinishActivityManager() {
-
}
-
private static FinishActivityManager sManager;
-
private Stack<WeakReference<Activity>> mActivityStack;
-
public static FinishActivityManager getManager() {
-
if (sManager == null) {
-
synchronized (FinishActivityManager.class) {
-
if (sManager == null) {
-
sManager = new FinishActivityManager();
-
}
-
}
-
}
-
return sManager;
-
}
-
/**
-
* 添加Activity到栈
-
* @param activity
-
*/
-
public void addActivity(Activity activity) {
-
if (mActivityStack == null) {
-
mActivityStack = new Stack<>();
-
}
-
mActivityStack.add(new WeakReference<>(activity));
-
}
-
/**
-
* 检查弱引用是否释放,若释放,则从栈中清理掉该元素
-
*/
-
public void checkWeakReference() {
-
if (mActivityStack != null) {
-
// 使用迭代器进行安全删除
-
for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
-
WeakReference<Activity> activityReference = it.next();
-
Activity temp = activityReference.get();
-
if (temp == null) {
-
it.remove();
-
}
-
}
-
}
-
}
-
/**
-
* 获取当前Activity(栈中最后一个压入的)
-
* @return
-
*/
-
public Activity currentActivity() {
-
checkWeakReference();
-
if (mActivityStack != null && !mActivityStack.isEmpty()) {
-
return mActivityStack.lastElement().get();
-
}
-
return null;
-
}
-
/**
-
* 关闭当前Activity(栈中最后一个压入的)
-
*/
-
public void finishActivity() {
-
Activity activity = currentActivity();
-
if (activity != null) {
-
finishActivity(activity);
-
}
-
}
-
/**
-
* 关闭指定的Activity
-
* @param activity
-
*/
-
public void finishActivity(Activity activity) {
-
if (activity != null && mActivityStack != null) {
-
// 使用迭代器进行安全删除
-
for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
-
WeakReference<Activity> activityReference = it.next();
-
Activity temp = activityReference.get();
-
// 清理掉已经释放的activity
-
if (temp == null) {
-
it.remove();
-
continue;
-
}
-
if (temp == activity) {
-
it.remove();
-
}
-
}
-
activity.finish();
-
}
-
}
-
/**
-
* 关闭指定类名的所有Activity
-
* @param cls
-
*/
-
public void finishActivity(Class<?> cls) {
-
if (mActivityStack != null) {
-
// 使用迭代器进行安全删除
-
for (Iterator<WeakReference<Activity>> it = mActivityStack.iterator(); it.hasNext(); ) {
-
WeakReference<Activity> activityReference = it.next();
-
Activity activity = activityReference.get();
-
// 清理掉已经释放的activity
-
if (activity == null) {
-
it.remove();
-
continue;
-
}
-
if (activity.getClass().equals(cls)) {
-
it.remove();
-
activity.finish();
-
}
-
}
-
}
-
}
-
/**
-
* 结束所有Activity
-
*/
-
public void finishAllActivity() {
-
if (mActivityStack != null) {
-
for (WeakReference<Activity> activityReference : mActivityStack) {
-
Activity activity = activityReference.get();
-
if (activity != null) {
-
activity.finish();
-
}
-
}
-
mActivityStack.clear();
-
}
-
}
-
/**
-
* 退出应用程序
-
*/
-
public void exitApp() {
-
try {
-
finishAllActivity();
-
// 退出JVM,释放所占内存资源,0表示正常退出
-
System.exit(0);
-
// 从系统中kill掉应用程序
-
android.os.Process.killProcess(android.os.Process.myPid());
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
}
-
}
代码一目了然,之所以改成Stack,是因为要模仿Activity的任务栈的方式,关闭最后打开的Activity更加方便。 使用的话,在BaseActivity中onCreate()中addActivity,在onDestroy()中finishActivity(),其他功能在各个子Activity中根据需要添加。
优劣: 优点:一劳永逸,一次封装,方便后续使用。 缺点:暂无。
方案四:launchMode
根据Android启动模式,standard和singleTop并不能实现项目需求,故排除。
singleTask和singleInstance在使用的时候会和onActivityResult()有点关系: Android 5.0以上的版本能正常使用,没有冲突; Android 5.0以下的版本有个bug,在调用了startActivityForResult之后立马就会调用onActivityResult,不会等到打开的Activity返回的时候才调用。 项目中很多Activity种都有startActivityForResult,故此种方式排除掉。
方案五:onActivityResult
根据方案四,此方式需要配合launchMode的standard和singleTop使用才能达到效果,所以局限性很大。
总结
以上就是几种方案的对比,要是项目中需要关闭Activity不多,不需要发送大量广播,可以使用方案一;方案二和方案三有异曲同工之处,首先推荐方案三。
能力有限,有不对之处,欢迎指出。
参考资料: 《深入理解Java虚拟机:JVM高级特性与最佳实践》
http://blog.csdn.net/weiwozhiyi/article/details/50791416