对Activity管理(附源码理解)

来源:互联网 发布:汽修厂管理接待软件 编辑:程序博客网 时间:2024/05/22 12:02

相信很多刚入行的朋友在开发界面繁多,逻辑复杂的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



0 0
原创粉丝点击