android判断往返方向,Activity跳转实现“从哪儿来回哪去”

标题中引号的内容,相信各位Android程序员会碰到这样的需求。特别是当一个功能有多个入口的时候,更种跳转会让人抓狂。有时候我们会利用Activity的SingleTask模式来完成清栈操作,但当业务场景变的复杂的时候,就需要我们考虑其他方式了。

情景一

Activity的跳转路径为:

A->B->C->D->E->A。

最终要求存在栈里面的Activity只有A。

实现

通过设置Activity A为SingleTask模式可以完成该跳转操作(当然前提是要求所有Activity在同一个Task里面)。同时,我们也可以通过自定义一个Activity栈来完成该操作。代码如下:

import android.app.Activity;

import java.util.ArrayList;

/**

* help to manager activity stack

* @author kisson

*/

public class ActivityStackManager {

private static ArrayList sActivityList = new ArrayList<>();

private static class ActivityStackManagerHolder {

private static ActivityStackManager sInstance = new ActivityStackManager();

}

public static ActivityStackManager getInstance() {

return ActivityStackManagerHolder.sInstance;

}

public void addActivity(Activity activity) {

sActivityList.add(activity);

}

/**

* back to target activity

*

* @param addTime the add time of target activity

* @return true if back to target activity successfully

*/

public boolean back2TargetActivity(String addTime) {

if (isTargetActivityExist(addTime)) {

for (int i = sActivityList.size() - 1; i >= 0; i--) {

String var = ((BaseActivity) sActivityList.get(i)).getAddTime();

if (!var.equals(addTime)) {

popActivityFromStack(sActivityList.get(i));

} else {

return true;

}

}

}

return false;

}

/**

* back to target activity

*

* @param indexActivityClass the class of target activity

* @return true if back to target activity successfully

*/

public boolean back2TargetActivity(Class indexActivityClass) {

if (isTargetActivityExist(indexActivityClass)) {

for (int i = sActivityList.size() - 1; i >= 0; i--) {

if (sActivityList.get(i).getClass() != indexActivityClass) {

popActivityFromStack(sActivityList.get(i));

} else {

return true;

}

}

}

return false;

}

private boolean isTargetActivityExist(String addTime) {

for (Activity activity : sActivityList) {

if(activity == null){

continue;

}

if (((BaseActivity) activity).getAddTime().equals(addTime)) {

return true;

}

}

return false;

}

private boolean isTargetActivityExist(Class targetActivityClass) {

for (Activity activity : sActivityList) {

if(activity == null){

continue;

}

if (activity.getClass() == targetActivityClass) {

return true;

}

}

return false;

}

private void popActivityFromStack(Activity activity) {

if (activity != null && !activity.isFinishing()) {

activity.finish();

sActivityList.remove(activity);

}

}

public void removeActivity(Activity activity) {

sActivityList.remove(activity);

}

}

以上写的Activity栈管理器比较简单,我们可以根据需求进行拓展。接着定义一个BaseActivity类,来完成入栈和出栈等相关操作,代码如下。

import android.app.Activity;

import android.os.Bundle;

import android.os.SystemClock;

/**

* Created by kisson on 16/6/7.

*/

public class BaseActivity extends Activity {

private String addTime;

public String getAddTime() {

return addTime;

}

public void setAddTime(String addTime) {

this.addTime = addTime;

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setAddTime(String.valueOf(SystemClock.currentThreadTimeMillis()));

ActivityStackManager.getInstance().addActivity(this);

}

@Override

protected void onDestroy() {

super.onDestroy();

ActivityStackManager.getInstance().removeActivity(this);

}

}

这里在BaseActivity中定义了addTime变量,那么它的作用什么?

比如Activity的跳转路径为:

A->B->C->D->B'->E。

在该跳转路径上Activity B 出现两次(Activity B的启动模式为standard),虽然它们是同一个Activity,但是是不同的的实例,因此通过Class来区分就显得不够用了。所以,在这里添加addTime变量,用于保证Activity实例的唯一性。

接着,我们需要实现一个辅助类用于完成“情景一”的跳转。

package com.dighammer.kisson.goback;

import android.app.Activity;

import java.util.ArrayList;

import java.util.List;

/**

* Created by kisson on 16/6/8.

*/

public class ActivityPathManager {

/**

* 这里用数组记录源Activity而不是单独用一个String,是因为:在某一个跳转路径上可能有多个注册源Activity行为

* 比如A->B->C-D-A,在A中进行注册源Activity,

* 同时另外一条链路M->N->B->C->D->M(当然这两条链路是不可能同时发生的),需要在B中注册源Activity。但是这两条链路有重合部分,

* 如果仅仅用String来表示addTime,会存在覆盖的情况,因此用数组来保存addTime,但是只有第一条数据有效。

**/

private static List sAddTimeList = new ArrayList<>();

private static List> sActivityClassList = new ArrayList<>();

private static class ActivityPathManagerHolder {

private static ActivityPathManager sInstance = new ActivityPathManager();

}

public static ActivityPathManager getInstance() {

return ActivityPathManagerHolder.sInstance;

}

/**

* 注册源Activity

*

* @param addTime Activity的创建时间,可以唯一表示某一Activity

*/

public void registerSourceActivity(String addTime) {

sAddTimeList.add(addTime);

}

/**

* 注册源Activity

*

* @param indexClass Activity的类名

*/

public void registerSourceActivity(Class indexClass) {

sActivityClassList.add(indexClass);

}

/**

* 当从源Activity通过任意跳转路径到达目标Activity时,调用此方法后可以返回到源Activity

*

* @return 如果是true,直接跳转到源Activity;如果是false,走原有逻辑

*/

public boolean back2SourceActivity() {

if (!sAddTimeList.isEmpty()) {

ActivityStackManager.getInstance().back2TargetActivity(sAddTimeList.get(0));

clearAddTime();

return true;

}

return false;

}

/**

* 当从源Activity通过任意跳转路径到达目标Activity时,调用此方法后可以返回到源Activity

*

* @return 如果是true,直接跳转到源Activity;如果是false,走原有逻辑

*/

public boolean back2SourceActivity2() {

if (!sActivityClassList.isEmpty()) {

ActivityStackManager.getInstance().back2TargetActivity(sActivityClassList.get(0));

clearClass();

return true;

}

return false;

}

/**

* 当从源Activity通过任意跳转路径到达目标Activity时,调用此方法后可以返回到源Activity,此方法不需要注册Activity

*

* @param addTime 源Activity的添加时间

* @return 如果是true,直接跳转到源Activity;如果是false,走原有逻辑

*/

public boolean back2SourceActivity(String addTime) {

if (addTime != null) {

ActivityStackManager.getInstance().back2TargetActivity(addTime);

return true;

}

return false;

}

/**

* 当从源Activity通过任意跳转路径到达目标Activity时,调用此方法后可以返回到源Activity,此方法不需要注册Activity

*

* @param indexClass 源Activity的类

* @return 如果是true,直接跳转到源Activity;如果是false,走原有逻辑

*/

public boolean back2SourceActivity(Class indexClass) {

if (indexClass != null) {

ActivityStackManager.getInstance().back2TargetActivity(indexClass);

return true;

}

return false;

}

private void clearAddTime() {

sAddTimeList.clear();

}

private void clearClass() {

sActivityClassList.clear();

}

/**

* 清除所有已经注册Activity的addTime

* notice:在你的源Activity的onCreate和onRestart方法调用该方法!

*/

public void unregisterSourceActivity(String addTime) {

sAddTimeList.remove(addTime);

}

/**

* 清除所有已经注册Activity的Class

* notice:在你的源Activity的onCreate和onRestart方法调用该方法!

*/

public void unregisterSourceActivity(Class indexClass) {

sActivityClassList.remove(indexClass);

}

}

用法

在源Activity中通过调用ActivityPathManager的registerSourceActivity方法进行注册(注意在源Activity的onCreate和onRestart方法进行注销),比如。

public void onClick(View view) {

startActivity(new Intent(SourceActivity.this, AActivity.class));

ActivityPathManager.getInstance().registerSourceActivity(getAddTime());

}

在最终跳转到的目标Activity通过调用ActivityPathManager的back2SourceActivity方法返回到源Activity,比如。

public void onClick(View view){

ActivityPathManager.getInstance().back2SourceActivity();

}

最终的结果可以成功返回到源Activity。

情景二

本文所实现的“从哪来回哪去”功能并不能顾及到所有跳转情况,但是我们可以根据需求在此基础上进行拓展。

比如跳转路径为A->B->C->D->E->F。

最终要求栈里只有A和F,并且F后退是返回到A的。

这种跳转需求,Activity的四种启动模式就无法搞定了。

但是我们可以增加ActivityPathManager和ActivityStackManager类中的方法,来完成相应的功能。

在ActivityStackManager类中增加back2TargetActivityExceptTop方法,代码如下。

/**

* back to target activity but do not pop the top activity

*

* @param addTime the add time of target activity

* @return true if back to target activity successfully

*/

public boolean back2TargetActivityExceptTop(String addTime) {

if (isTargetActivityExist(addTime)) {

for (int i = sActivityList.size() - 2; i >= 0; i--) {

String var = ((BaseActivity) sActivityList.get(i)).getAddTime();

if (!var.equals(addTime)) {

popActivityFromStack(sActivityList.get(i));

} else {

return true;

}

}

}

return false;

}

通用在ActivityPathManager类中增加back2SourceActivityExceptTop方法,代码如下:

public boolean back2SourceActivityExceptTop() {

if (!sAddTimeList.isEmpty()) {

ActivityStackManager.getInstance().back2TargetActivityExceptTop(sAddTimeList.get(0));

clearAddTime();

return true;

}

return false;

}

最后

欢迎大家来提出宝贵意见,或者某些情景下,本文功能无法实现的!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值