相信很多刚入行的朋友在开发界面繁多,逻辑复杂的App的时候对Activity的管理很是头疼。尽管论坛上面很多关于Activity管理的资源,但是注释明确清晰(简单易懂)的还是挺少的,所以博主发一下自己对这方面的见解,如有什么有错误的地方,请指出,同时多多包涵,好啦,不说这么多客套话了。Coding time!
下面我附一个网上很实用的一个管理Activity的类文件:
package com.example.lenovo.mproject;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import java.util.Stack;
/**
* Created by wz on 2016/6/23.
*/
public class AppManager {
// Activity栈
private static Stack<Activity> activityStack;
// 单例模式
private static AppManager instance;
private AppManager() {
}
/**
* 单一实例
*/
public static AppManager getAppManager() {
if (instance == null) {
instance = new AppManager();
}
return instance;
}
/**
* 添加Activity到堆栈
*/
public void addActivity(Activity activity) {
if (activityStack == null) {
activityStack = new Stack<Activity>();
}
activityStack.add(activity);
}
/**
* 获取当前Activity(堆栈中最后一个压入的)
*/
public Activity currentActivity() {
Activity activity = activityStack.lastElement();
return activity;
}
/**
* 结束当前Activity(堆栈中最后一个压入的)
*/
public void finishActivity() {
Activity activity = activityStack.lastElement();
finishActivity(activity);
}
/**
* 结束指定的Activity
*/
public void finishActivity(Activity activity) {
if (activity != null) {
activityStack.remove(activity);
activity.finish();
activity = null;
}
}
/**
* 结束指定类名的Activity
*/
public void finishActivity(Class<?> cls) {
for (Activity activity : activityStack) {
if (activity.getClass().equals(cls)) {
finishActivity(activity);
}
}
}
/**
* 结束所有Activity
*/
public void finishAllActivity() {
for (int i = 0; i < activityStack.size(); i++) {
if (null != activityStack.get(i)) {
activityStack.get(i).finish();
}
}
activityStack.clear();
}
/**
* 退出应用程序
*/
public void AppExit(Context context) {
try {
finishAllActivity();
ActivityManager activityMgr = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
activityMgr.killBackgroundProcesses(context.getPackageName());
System.exit(0);
} catch (Exception e) {
}
}
}
一、压入栈中和获取栈顶Activity
/**
* 添加Activity到堆栈
**/
public void addActivity(Activity activity) {
if (activityStack == null) {
activityStack = new Stack<Activity>();
}
activityStack.add(activity);
}
/**
* 获取当前Activity(堆栈中最后一个压入的)
*/
public Activity currentActivity() {
Activity activity = activityStack.lastElement();
return activity;
}
在此之前我们需要Stack这个类,Stack中文翻译是栈的意思,我们知道在默认的标准Activity启动模式中(standard),Activity在栈中遵循先入后出的规则,所以当我们需要灵活
的去管理这些压入栈中的Activity时,需要自己使用单例创建一个专门用于管理Activity的管理类,该工具类中就是使用Stack这个集合去管理集合内的所有Activity,这使我们在需
要管理的Activity类中必须把该类add进这个栈的集合,在获取栈顶的Activity时候(也就是堆栈最后一个压入的或者说是当前的Activity),调用了LastElement法:
/**
* Returns the last element in this vector.
*
* @return the element at the last position.
* @throws NoSuchElementException
* if this vector is empty.
* @see #elementAt
* @see #firstElement
* @see #size
*/
@SuppressWarnings("unchecked")
public synchronized E lastElement() {
try {
return (E) elementData[elementCount - 1];
} catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
<span style="font-size:18px;"><strong> 二、从栈中移除指定Activity
</strong></span><pre name="code" class="java"> /**
* 结束指定的Activity
*/
public void finishActivity(Activity activity) {
if (activity != null) {
activityStack.remove(activity);
activity.finish();
activity = null;
}
}
从源码中可以看出,返回了栈集合中最后一个(也就是栈顶或者说是当前的Activity)的元素,elementCount也就是这个压入栈中元素的个数。
我们接着看下去:
/**
* 结束指定的Activity
*/
public void finishActivity(Activity activity) {
if (activity != null) {
activityStack.remove(activity);
activity.finish();
activity = null;
}
}
当我们调用结束指定的这个方法时,在该Activity存在或者是未被GC机制回收的情况下该调用该栈集合的remove方法:
/**
* Removes the first occurrence, starting at the beginning and moving
* towards the end, of the specified object from this vector. All elements
* with an index bigger than the element that gets removed have their index
* decreased by 1.
*
* @param object
* the object to remove from this vector.
* @return {@code true} if the specified object was found, {@code false}
* otherwise.
* @see #removeAllElements
* @see #removeElementAt
* @see #size
*/
@Override
public boolean remove(Object object) {
return removeElement(object);
}
<pre name="code" class="java"> /**
* Removes the first occurrence, starting at the beginning and moving
* towards the end, of the specified object from this vector. All elements
* with an index bigger than the element that gets removed have their index
* decreased by 1.
*
* @param object
* the object to remove from this vector.
* @return {@code true} if the specified object was found, {@code false}
* otherwise.
* @see #removeAllElements
* @see #removeElementAt
* @see #size
*/
public synchronized boolean removeElement(Object object) {
int index;
if ((index = indexOf(object, 0)) == -1) {
return false;
}
removeElementAt(index);
return true;
}
/**
* Searches in this vector for the index of the specified object. The search
* for the object starts at the beginning and moves towards the end of this
* vector.
*
* @param object
* the object to find in this vector.
* @return the index in this vector of the specified element, -1 if the
* element isn't found.
* @see #contains
* @see #lastIndexOf(Object)
* @see #lastIndexOf(Object, int)
*/
@Override
public int indexOf(Object object) {
return indexOf(object, 0);
}
/**
* Searches in this vector for the index of the specified object. The search
* for the object starts at the specified location and moves towards the end
* of this vector.
*
* @param object
* the object to find in this vector.
* @param location
* the index at which to start searching.
* @return the index in this vector of the specified element, -1 if the
* element isn't found.
* @throws ArrayIndexOutOfBoundsException
* if {@code location < 0}.
* @see #contains
* @see #lastIndexOf(Object)
* @see #lastIndexOf(Object, int)
*/
public synchronized int indexOf(Object object, int location) {
if (object != null) {
for (int i = location; i < elementCount; i++) {
if (object.equals(elementData[i])) {
return i;
}
}
} else {
for (int i = location; i < elementCount; i++) {
if (elementData[i] == null) {
return i;
}
}
}
return -1;
}
/**
* Removes the element found at index position {@code location} from
* this {@code Vector}. All elements with an index bigger than
* {@code location} have their index decreased by 1.
*
* @param location
* the index of the element to remove.
* @throws ArrayIndexOutOfBoundsException
* if {@code location < 0 || location >= size()}.
* @see #removeElement
* @see #removeAllElements
* @see #size
*/
public synchronized void removeElementAt(int location) {
if (location >= 0 && location < elementCount) {
elementCount--;
int size = elementCount - location;
if (size > 0) {
System.arraycopy(elementData, location + 1, elementData,
location, size);
}
elementData[elementCount] = null;
modCount++;
} else {
throw arrayIndexOutOfBoundsException(location, elementCount);
}
}
从源码看这几个方法在Vector这个类中,而Stack类又是继承的Vector,在移除指定的Activity时候前遍历这个集合获取到指定Activity栈的index,然后通过removeElementAt(int index),这个方法里面有意思的一个方法也就是:
System.arraycopy(elementData, location + 1, elementData,
location, size);
讲真,博主以前也没用过和听说过,经过大概的了解,这里也和大家简单介绍一下:这个方法主要用于对大型集合的复制,因为一般的集合复制需要我们去遍历,当集合过多,对于性能的影响会比较大。这里我们常用的方法是这样:
public static native void arraycopy(Object src, int srcPos,
Object dst, int dstPos, int length);
简单介绍一下该方法:也就是从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。从 src 引用的源数组到 dest 引用的目标数组,数组组件的一个子序列被复制下来。被复制的组件的编号等于 length 参数。源数组中位置在 srcPos 到 srcPos+length-1 之间的组件被分别复制到目标数组中的 destPos 到 destPos+length-1 位置。
回到刚刚的removeElementAt方法中,当栈的集合长度减一等于被移除的下标的时候(也就是栈顶时候),size>0返回false,然后给指定的Activity对象赋NULL值。当指定移除的Activity不是出于栈顶时,size>0返回true,通过arraycopy方法对该栈集合进行重组,把被指定的Activity排在最后一个元素然后一样把该元素赋NULL值。可能会有人疑问,你怎么说集合被重组了??下面我贴出源码的关键代码:
if (size > 0) {
System.arraycopy(elementData, location + 1, elementData,
location, size);
}
这层判断刚刚我已经说明了:
当指定移除的Activity不是出于栈顶时,size>0返回true
同时也介绍过arraycopy方法,这里可以看出是复制elementData从下标location+1到下标location+1+size-1给elementData的下标location到下标location+size-1。
上面这段逻辑可能有点绕,但是静下来理一理就好了。
location+1+size-1我们可以进行换算,从上面源码可以看到size=elementCount-location 也就是location+1+size-1 = location+1+elementCount-location-1 = elementCount 这
样看是不是思路清晰一些了。
三、清空堆栈(退出程序)
/**
* 结束所有Activity
*/
public void finishAllActivity() {
for (int i = 0; i < activityStack.size(); i++) {
if (null != activityStack.get(i)) {
activityStack.get(i).finish();
}
}
activityStack.clear();
}
/**
* 退出应用程序
*/
public void AppExit(Context context) {
try {
finishAllActivity();
ActivityManager activityMgr = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
activityMgr.killBackgroundProcesses(context.getPackageName());
System.exit(0);
} catch (Exception e) {
}
}
相信很多人都在懊恼程序不能够完全退出的问题,反正博主是遇见过,后来还是解决了。不废话了,看上面的代码可知道是遍历单例出来的管理集合,然后去结束掉所有的Actvitiy,然后清空这个堆栈集合,最后获取到ActivityManager去杀死掉所有的后台进程,最后退出程序,保证退出后所有的后台服务也被销毁。
这次对于源码简单的分析就到这里,希望能够帮助到需要的人,如果有什么错误的地方,希望大家能够指出,我谦虚学习请教。
最后祝大家工作顺利,走上人生巅峰。。
附源码:http://download.csdn.net/detail/u011862733/9568978