一、出现场景
最近本人在做公司项目的时候,有一个需求就是将activity最小化,然后启动Service悬浮窗的需求,此时就必须将此Activity的启动模式设置为singleInstance,否则最小化(即调用moveTaskToBack(true)这个方法)时app直接跳至lancher界面,这样就达不到我们想要的效果。
二、新的问题
熟悉activity的四种启动模式的同学都应该清楚,当Activity启动模式设置为SingleInstance后,当start此activity时会单独开启一个任务栈,当我们有需要从此activity跳转到另一个activity处理需求的时候,就会出现我们处理完需求后finish后一个activity时,就返回不到此activity了。
不熟悉Activity启动模式的同学,要想理解此篇博文,必须先去熟悉下。网上关于这方面的资源很多,我就不多讲了。
三、解决办法
1、参考资料:
我的解决办法是在https://blog.csdn.net/Mr_JingFu/article/details/79077613这篇文章上进行修改的,大家可以去看看,然后结合自己的需求可以进行选择。
2、解决思路
1)、新建一个activity的管理类,新增一个列表list,在BaseActivity中当我们打开一个activity时将此activity添加进去,关闭时将此activity时移除。
2)、当我们关闭一个activity时,会自动调用前一个activity的onRestart——>onStart——>onResume方法,此时我们
可以在onStart方法进行判断,此activity是否与list中最后一个Activity是否为同一个,如果是就不做任何逻辑,不是的话list最后一个Activity的启动模式就有可能singleInstance,那我们就手动跳转到此Activity中,问题初步就得到解决了。
3)、为什么说只能说是有可能呢,因为当我们将启动模式为singleInstance的Activity最小化的时候,此Activity并没有关闭,而是在后台中继续运行,此时如果我们不做任何判断的话,就会出现当我们最小化的时候,又重新打开此Activity了。原因就是此时list中最后一个Activity就是当前启动模式为singleInstance的Activity.
4)、为解决这个问题,我们必须再添加一个启动模式为singleInstance的Activity的singleInstanceList.当启动此activity时,添加进去,关闭时和最小化的时候移除。在onstart方法中多加一层判断,当次activity与list中最后一个Activity不为同一个时,将list中的activity与singleInstanceList中的Activity进行比对,如果singleInstanceList存在此Activity,这时候这个activity就是我们所要跳转的activity,那么我们直接跳过去就可以了。值得一提的是,当我们从新打开启动模式为singleInstance的activity的时候,并不会走oncreate——>onStart()——>onResume()方法,而是走onNewIntent()——>onRestart()——>onStart()——>onResume()方法,此时我们必须得在这后面三个方法其中一个将此activity添加到singleInstanceList中。当然,我自己是在onStart方法中添加的。
3 关键代码
1)、appManager中相关代码
public class AppManger {
private static List<Activity> mActivityStack = new ArrayList<>();
private static AppManger mAppManager;
private List<Activity> mSingleInstanceStack = new ArrayList<>();
private AppManger() {
}
/**
* 单一实例
*/
public static AppManger getInstance() {
if (mAppManager == null) {
synchronized (AppManger.class) {
if (mAppManager == null) {
mAppManager = new AppManger();
}
}
}
return mAppManager;
}
public void remove(Activity activity) {
if (activity != null) {
mActivityStack.remove(activity);
}
}
/**
* 添加Activity到堆栈
*/
public void addActivity(Activity activity) {
if (mActivityStack == null) {
mActivityStack = new ArrayList<Activity>();
}
mActivityStack.add(activity);
}
/**
* 添加singleInstanceActivity
*/
public void addSingleInstanceActivity(Activity activity) {
if (!isAddSingleInstanceActivity(activity.getClass()))
mSingleInstanceStack.add(activity);
}
/**
* 移除singleInstanceActivity
*/
public void removeSingleInstanceActivity(Activity activity) {
if (activity != null)
mSingleInstanceStack.remove(activity);
}
public List<Activity> getmSingleInstanceStack() {
return mSingleInstanceStack;
}
/**
* 查看某个singleInstanceActivity是否被添加过
*
* @param cls
*/
public boolean isAddSingleInstanceActivity(Class<?> cls) {
int size = mSingleInstanceStack.size();
if (size > 0)
for (int i = size - 1; i >= 0; i--) {
if (mSingleInstanceStack.get(i).getClass() == cls) {
return true;
}
}
return false;
}
/**
* 获取栈顶Activity(堆栈中最后一个压入的)
*/
public Activity getTopActivity() {
if (mActivityStack == null) {
return null;
}
Activity activity = mActivityStack.get(mActivityStack.size() - 1);
return activity;
}
/**
* 结束指定的Activity
*/
public void killActivity(Activity activity) {
if (activity != null) {
mActivityStack.remove(activity);
activity.finish();
activity = null;
}
}
/**
* 结束指定类名的Activity
*/
public void killActivity(Class<?> cls) {
int size = mActivityStack.size();
L.e("栈内activity长度为-------------" + size);
if (size > 0)
for (int i = size - 1; i >= 0; i--) {
if (mActivityStack.get(i).getClass() == cls) {
mActivityStack.get(i).finish();
}
}
}
/**
* 结束所有Activity
*/
public void killAllActivity() {
for (int i = 0, size = mActivityStack.size(); i < size; i++) {
if (null != mActivityStack.get(i)) {
mActivityStack.get(i).finish();
}
}
mActivityStack.clear();
}
/**
* 关闭所选所以之外的activity
*/
public void KillexceptActivitiy(Activity activity) {
int size = mActivityStack.size();
for (int i = size - 1; i >= 0; i--) {
if (mActivityStack.get(i) != activity) {
mActivityStack.get(i).finish();
}
}
}
/**
* 查看某个activity是否被添加过
*
* @param cls
*/
public boolean isAddActivity(Class<?> cls) {
Iterator<Activity> iterator = mActivityStack.iterator();
while (iterator.hasNext()) {
Activity activity = iterator.next();
if (activity.getClass().equals(cls)) {
return true;
}
}
return false;
}
/**
* 结束栈顶Activity(堆栈中最后一个压入的)
*/
public void killTopActivity() {
Activity activity = mActivityStack.get(mActivityStack.size() - 1);
killActivity(activity);
}
/**
* 关闭所选所以之外的activity
*/
public void KillexceptActivitiy(Class<?> cls) {
int size = mActivityStack.size();
for (int i = size - 1; i >= 0; i--) {
if (mActivityStack.get(i).getClass() != cls) {
mActivityStack.get(i).finish();
}
}
}
/**
* 结束到类名的Activity
*/
public void killTOActivity(Class<?> cls) {
for (int i = mActivityStack.size() - 1; i >= 0; i--) {
if (null != mActivityStack.get(i)) {
if (mActivityStack.get(i).getClass().equals(cls)) {
killActivity(mActivityStack.get(i));
}
}
}
}
/**
* 是否有打开app
*
* @return
*/
public boolean isOpenActivity() {
if (mActivityStack == null) {
return false;
} else if (mActivityStack.size() == 0) {
return false;
}
return true;
}
/**
* 退出应用程序
*/
public void AppExit(Context context) {
try {
killAllActivity();
ActivityManager activityMgr = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
activityMgr.restartPackage(context.getPackageName());
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2)BaseActivity中相关代码
@Override
protected void onStart() {
checkInstanceActivity();
super.onStart();
}
@Override
public void finish() {
removeActivity();
super.finish();
}
/**
* 释放资源
*/
private void removeActivity() {
AppManger.getInstance().remove(this);
}
private void checkInstanceActivity() {//判断栈顶activity
if (AppManger.getInstance().getTopActivity() != null) {
if (!AppManger.getInstance().getTopActivity().getClass().getName().equals(this.getClass().getName())) {
if (AppManger.getInstance().getmSingleInstanceStack().size() > 0)
for (int i = AppManger.getInstance().getmSingleInstanceStack().size() - 1; i >= 0; i--) {
if (AppManger.getInstance().getmSingleInstanceStack().get(i).getClass().getName().equals(AppManger.getInstance().getTopActivity().getClass().getName())) {
startActivity(AppManger.getInstance().getTopActivity().getClass(), null);
return;
}
}
}
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
apolloBinder = Apollo.bind(this);//事件通知进行绑定
DaggerCommonComponent.builder().netWorkMoudle(new NetWorkMoudle(this)).build().inject(this);
ActivityCollector.addActivity(this);
AppManger.getInstance().addActivity(this);
//注:该方法是【友盟+】Push后台进行日活统计及多维度推送的必调用方法,请务必调用!
PushAgent.getInstance(this).onAppStart();
}
3)启动模式有singleInstance的activity的关键用法
//最小化语聊房同时打开悬浮窗
public void minimizeRoom() {
AppManger.getInstance().removeSingleInstanceActivity(this);//最小化时移除此单例activity
moveTaskToBack(true);//最小化Activity
Intent intent = new Intent(this, FloatChatRoomWindowService.class);//开启服务显示悬浮框
Bundle bundle = new Bundle();
bundle.putBoolean("sound", db.cbSound.isChecked());
bundle.putInt("room_id", room_id);
bundle.putString("avatar", roomInfo.getAvatar());
intent.putExtras(bundle);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
isShowFloating = true;
}
@Override
protected void onStart() {
super.onStart();
AppManger.getInstance().addSingleInstanceActivity(this);
}
/**
* 内存泄漏解决方案
* 在使用分享或者授权的Activity中,重写onDestory()方法:
*/
@Override
protected void onDestroy() {
super.onDestroy();
UMShareAPI.get(this).release();
AppManger.getInstance().removeSingleInstanceActivity(this);
}
4、结束语
虽然我话说的比较多,但是具体思路确实是这样子的。希望能帮助到大家!如果对大家有所帮助的话,请大家给个赞。