对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
- 对Activity管理(附源码理解)
- EasyUI管理后台模板(附源码)
- EasyUI管理后台模板(附源码)
- Activity的生命周期附源码
- android中Activity的生命周期(附测试源码)
- Android Service Activity三种交互方式(附源码)
- Android Instrumentation源码分析(附Activity启动流程)
- 对Activity的理解
- 对Activity的理解
- 对REST架构的理解及Jquery+JSON+RESTful WCF (附源码)
- 对多态的理解(附经典练习题)
- Android小项目之学生管理系统(附源码)
- 对Activity生命周期的理解
- 我对 Activity 的理解
- 源码角度深入理解Activity
- Activity对对话框的管理
- Activity对Dialog的管理
- AMS对Activity的管理
- JAVA值传递与引用传递
- 聊聊Linux 五种IO模型
- HTTP深入浅出 http请求
- 认识循环
- 46. Permutations --- leetcode 算法笔记
- 对Activity管理(附源码理解)
- linux驱动模块开机自动加载,以及应用程序开机自启动
- Robot framwork case执行命令
- jQuery – 自动完成(Autocomplete)
- 设置mysql外部ip可以访问的命令
- matlab-自控原理 已知传递函数,求其阶跃响应
- spring MVC配置详解
- Maven pom.xml 配置详解
- iOS开发-数据持久化