【Android 应用开发】 Application 使用分析
博客地址 :http://blog.csdn.net/shulianghan/article/details/40737419
代码下载 : Android 应用 Application 经典用法;
-- Github :https://github.com/han1202012/ApplicationDemo
-- CSDN :http://download.csdn.net/detail/han1202012/8127247
一. Application 分析
1. Application 简介
(1) Application 概念
Application 概念 : Application 属于组件范畴;
-- 本质 : Application 与 四大组件 一样也属于 Android 中的组件;
-- 作用 : 用于存储系统 和 用户定义的全局信息;
-- Application 创建 : 应用开始运行时创建 Application 对象, 可以自定义, 也可以让系统自动创建;
-- Application 单例性 : 每个应用只创建一个 Application 对象, 该类属于单例模式;
-- Application 生命周期 : Application 生命周期 从应用启动开始 到 应用退出结束, 与应用的生命周期是相同的;
-- Application 作用 : 在任何组件中调用 getApplication() 或者通过 Context 对象调用 getApplicationContext() 方法获取的 Application 对象都是相同的, 因此可以使用 Application 进行数据共享, 数据缓存操作;
(2) Application 与 全局变量
Application 与 全局变量 :
-- 基本作用 : Application 在 Android 中是为了 保存全局变量 而设计的类;
-- Android 全局变量定义 : 在 Android 中可以不使用 public static 定义全局变量, 定义在 Application 中的普通变量 在Android应用中可以当作全局变量使用;
(3) Application 使用方法
Application 使用方法 :
-- 自定义 Application : 自定义一个 class 类, 继承 android.app.Application 类;
-- 配置 Application : 在 AndroidManifest.xml 中配置 Application;
--获取 Application : 在组件类(Activity, Service 等)中直接调用 getApplication() 方法即可, 在普通类中调用 Context 的 getApplicationContext() 方法;
2. Application 生命周期 及 对应方法
(1) onCreate()
onCreate() 方法简介 : 该方法是 Android 程序的入口;
-- 执行时机 : 该方法在应用创建时自动回调;
-- 注意 : 在父类 Application 中, onCreate() 方法方法体是空的, 这里可以不用执行 super.onCreate()方法;
关于程序入口 :
-- Android 程序入口 : Android 程序入口是 Application, 并不是 Activity, 因为有的 应用是没有 Activity 的;
-- Java 和 C 程序入口 : 这两种语言的程序入口是工程中的 main() 函数;
(2) onLowMemory()
onLowMemory() 方法简介 :
-- 调用时机 : 在内存不足时会回调该方法;
-- 重写方法 : 重写时需要执行父类方法 super.onLowMemory(), 同时根据本应用特点, 释放掉一些不必要的数据;
(3) onTerminate()
onTerminate() 方法简介 :
-- 调用时机 : 只有在模拟器中终止程序时才会回调该方法, 在 Android 真机中是不会回调该方法的;
-- 注意 : Application 的 onTerminate() 方法体是空的, 这里不许要执行父类的方法 super.onTerminate();
(4)onConfigurationChanged()
onConfigurationChanged() 方法简介 :
-- 调用时机 : 配置改变时回调这个方法;
(5) Application 代码分析
Application 相关代码 :
/** * Called when the application is starting, before any other application * objects have been created. Implementations should be as quick as * possible (for example using lazy initialization of state) since the time * spent in this function directly impacts the performance of starting the * first activity, service, or receiver in a process. * If you override this method, be sure to call super.onCreate(). */ public void onCreate() { } /** * This method is for use in emulated process environments. It will * never be called on a production Android device, where processes are * removed by simply killing them; no user code (including this callback) * is executed when doing so. */ public void onTerminate() { } public void onConfigurationChanged(Configuration newConfig) { Object[] callbacks = collectComponentCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ComponentCallbacks)callbacks[i]).onConfigurationChanged(newConfig); } } } public void onLowMemory() { Object[] callbacks = collectComponentCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ComponentCallbacks)callbacks[i]).onLowMemory(); } } }
3. Application 使用场景 1 --> 组件间的数据传递
(1) 使用 Application 传递数据
Application 媒介传递数据方式 :
-- Appliction 集合 : 在 Application 中维护一个集合, 创建一个 HashMap 成员变量, 键是字符串, 值是 Object 对象, 这样 这个 HashMap 可以存储任何类型的对象;
-- 共享过程 : Activity A 将数据存储到 HashMap 中, 将 键 通过 Intent 的 Bundle 传递给 Activity B, 之后在 Activity B 中取出对象, 并将 HashMap 中的对象删除;
-- 适用范围 : 如果跳转的两个 Activity 在同一个 应用 中, 可以使用这种方法;
(2) 传统传递数据方式
传统数据传递 :Activity A 跳转到 Activity B;
-- 实体类 Bean 处理 : bean 实体类必须实现Serializable或者Parcellable接口, 才可以将实体类 bean 对象放入 Intent 的 Bundle 中;
-- 数据传递过程 : 在 Activity A 中将 实现了 Serializable 或者 Parcellable 接口的实体类对象放入 Intent 的 Bundle 中, 跳转到 Activity B;
4. Application 使用场景 2 --> 应用中的数据缓存
Application 缓存数据 :
-- 缓存少量数据 : 从互联网获取的少量数据可以直接存放在 Application 中用于数据缓存的 HashMap 中;
-- 缓存大量数据 : 如果缓存 数据 或者 文件, 可以将文件缓存到本地, 然后在 Application 中缓存一个 文件路径字符串即可;
-- 释放缓存 : 在 onLowMemory() 方法中可以释放这些缓存, 因为这些缓存可有可无, 这里为了性能牺牲访问速度;
数据传递, 缓存 Application 示例 :
package cn.org.octopus.application; import java.util.HashMap; import java.util.Map; import android.app.Application; public class MyApplication extends Application { /** 用于数据传递的 Map 集合 */ private Map<String, Object> transferMap; /** 用于缓存数据的 Map 集合 */ private Map<String, Object> cacheMap; @Override public void onCreate() { super.onCreate(); //初始化用于数据传递的 Map 集合 transferMap = new HashMap<String, Object>(); //初始化用于数据缓存的 Map 集合 cacheMap = new HashMap<String, Object>(); } /** * 获取数据传递 Map 集合 * @return * 数据传递 Map 集合 */ public Map<String, Object> getTransferMap() { return transferMap; } /** * 获取数据缓存 Map 集合 * @return * 数据缓存 Map 集合 */ public Map<String, Object> getCacheMap() { return cacheMap; } }
5. Application 与 内存泄漏
(1) Application 内存泄漏
Application 内存分析 :
-- 注意存放对象 : Application 中如果保存了一些大的对象, 例如 Activity 等组件, 如果没有释放, 将会引起很多内存泄漏;
-- 内存释放 : 在 Application 中要经常注意释放不许要的对象, 使用完毕后能释放掉的就释放, 在 onLowMemory() 方法中将所有的缓存数据都清空;
(2) Application 尽量不要持有 组件引用
组件持有 Context 对象 :
-- 创建组件 : TextView tv = new TextView(Activity activity), 这样一来 组件持有了 Activity 或者 Context 对象;
-- 组件持久化 : 当将持有 Context的 tv 组件设置为静态 或者 将 tv 组件设置到 Application 中时, tv 的声明周期就变成了整个应用的声明周期了;
-- Context 无法释放 : 此时 当 Activity 退出后, 组件仍然存在, Conetxt 无法释放, 一旦多次访问这个 Activity, 每次都会泄漏 Context 大小的内存;
防止内存泄漏方法 :
-- 组件 : Activity 中的组件的声明周期不要超出 Activity 生命周期;
-- 图片 : 组件使用的 Drawable 对象不要超出 Actiity 声明周期;
-- 线程持有对象 : 不要在线程中持有 Context, 否则在线程执行完毕之前都处于内存泄漏状态;
-- 内部类作用域不要超出 Activity : 如果在 Activity A 中定义了内部类, 不要将这个内部类传递给其它 Activity 等组件, 否则该 Activity A 不能释放, 建议将内部类设置成 static 或者 单独写成一个类;
二. Application 应用层源码分析
1. Application 类结构分析
(1) Application 继承关系
Application 类继承结构:
-- Application 类 :public class Application extends ContextWrapper implements ComponentCallbacks2 ;
-- ContextWrapper 类 :public class ContextWrapper extends Context ;
-- Context 类 :public abstract class Context;
-- ComponentCallbacks2 接口 :public interface ComponentCallbacks2 extends ComponentCallbacks ;
-- ComponentCallbacks 接口 :public interface ComponentCallbacks ;
-- UML 图 :
(2) 相关类介绍
Application 相关类介绍 :
-- Application 类 : 用于存储应用的全局变量;
-- ContextWrapper 类 : 该类是 Context 简单的代理实现, 代表了对另一个 Context 的调用, 在该类的子类中可以重写对应方法改变指定的操作行为;
-- Context 类 : 该 抽象类 是 应用环境的全局信息接口, Android 提供了该抽象类的实现类, 该类用于访问 应用的 资源 和 类 (作用一), 返回 应用的 Actiity, 广播, Intent 等操作的执行结果(作用二);
-- ComponentCallbacks2 接口 : 该接口继承了 ComponentCallbacks, 用于更细粒度的内存管理;
-- ComponentCallbacks 接口 :应用组件的回调接口, 所有的组件都要实现这个接口;
2. CompnentCallbacks 接口
部分源码 : 省略了注释部分, 代码完整;
package android.content; import android.content.res.Configuration; public interface ComponentCallbacks { void onConfigurationChanged(Configuration newConfig); void onLowMemory(); }
(1)onConfigurationChanged() 方法介绍
方法介绍 : 该方法回调后需要重新加载新配置对应的资源, 如果 Activity 对应配置改变需要 重启组件, 其它组件不用重启;
-- 方法全称 :void onConfigurationChanged(Configuration newConfig);
-- 回调时机: 在组件运行时, 如果发生了设备的配置改变, 就会回调该接口的方法;
-- 重新加载资源 : 当配置改变, 该方法回调后, 需要更新资源, 以找到与新配置匹配的资源, 例如屏幕方向改变了, 需要找 drawable-land (横屏) 或者 drawable-port (竖屏资源);
-- Activity 组件配置改变 : 当 Activity 运行的时候, 如果配置发生改变, 需要进行重新启动, 例如 横屏 切换 竖屏;
-- 其它组件配置改变 : 在 Service 等组件运行时, 配置发生改变, 不需要重新启动;
(2)onLowMemory() 方法介绍
方法介绍 :
-- 方法全称 :void onLowMemory();
-- 回调时机 : 当系统剩余内存比较低的时候, 并且系统想要 清理内存以获取更多内存时 回调该方法;
-- 时间点不确定 : 不能确定方法回调准确的时间点, 大概在所有的后台进行被杀死的时间点 左右 回调该方法, 这个时间点在 服务进程被杀死之前;
-- 避免杀死前台进程 : UI 进程在清理内存时, 是应该避免被杀死的, 这类进程尽量保存;
-- 方法中的建议操作 : 组件实现该方法, 在该方法中建议进行 释放缓存 或者 释放不需要持有的资源, 执行该方法后, 系统会执行 GC 垃圾回收;
3. ComponentCallbacks2 接口
源码示例 : 一部份源码, 省略了注释 和 一部份的 常量;
package android.content; public interface ComponentCallbacks2 extends ComponentCallbacks { static final int TRIM_MEMORY_COMPLETE = 80; static final int TRIM_MEMORY_MODERATE = 60; ... ... void onTrimMemory(int level); }
(1) onTrimMemory() 方法介绍
方法介绍 :
-- 方法全称 :void onTrimMemory(int level) ;
-- 回调时机 : 当 系统决定要清理一个进程不必要的内存时 回调该方法;
-- 清理内存时机 : 后台进程运行时, 当没有足够的内存去保持这些后台进程运行时, 就会进行内存清理;
-- 内存等级 : 每个等级都有一个对应的内存值, 但是这个内存等级的精确值是无法获取的, 因为随时都有新的中间值会累加上去;
(2) 内存等级常量介绍
LRU list 概念 : 全称 Least Recently Used, 即最近最少使用算法, 用于内存管理;
常量TRIM_MEMORY_COMPLETE :
-- 全称 :static final int TRIM_MEMORY_COMPLETE = 80;
-- 作用 : 表示 后台进程中的 LRU (最近最少使用) 队列的尾部, 如果需要更多内存, 这些进程将被杀死;
常量TRIM_MEMORY_MODERATE :
-- 全称 :static final int TRIM_MEMORY_MODERATE = 60 ;
-- 作用 : 表示 LRU 进程队列的 中间部分, 释放队列中间及后面进程的内存, 会提高手机性能;
常量用法 : 其中定义了很多类似的常量, 代表一部份进程, 将该常量传入onTrimMemory(int level) 可以杀死指定集合的进程;
4. Application 类分析
(1)ComponentCallbacks 集合列表
列表定义 :
-- 定义方式 :private ArrayList<ComponentCallbacks> mComponentCallbacks =new ArrayList<ComponentCallbacks>();
-- 使用位置 : 在onConfigurationChanged(),onLowMemory(),onTrimMemory() 方法中使用了 该列表;
-- 执行内容 : ComponentCallbacks 子类 即组件, 都实现了上面的三种方法, 在 Application 中的对应方法中分别遍历组件调用组件本身的对应方法;
注册 和 删除组件 : 每创建一个组件都将这个组件注册, 组件销毁时 从列表中删除组件;
public void registerComponentCallbacks(ComponentCallbacks callback) { synchronized (mComponentCallbacks) { mComponentCallbacks.add(callback); } } public void unregisterComponentCallbacks(ComponentCallbacks callback) { synchronized (mComponentCallbacks) { mComponentCallbacks.remove(callback); } }
(2)ActivityLifecycleCallbacks 接口介绍
ActivityLifecycleCallbacks 接口介绍 :
-- 接口作用 : 该接口提供了一套监测 Activity 声明周期的回调方法;
-- 注册 Activity 声明周期监听方法 :
public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) { synchronized (mActivityLifecycleCallbacks) { mActivityLifecycleCallbacks.add(callback); } }-- 取消监听方法 :
public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) { synchronized (mActivityLifecycleCallbacks) { mActivityLifecycleCallbacks.remove(callback); } }-- 接口代码 :
public interface ActivityLifecycleCallbacks { void onActivityCreated(Activity activity, Bundle savedInstanceState); void onActivityStarted(Activity activity); void onActivityResumed(Activity activity); void onActivityPaused(Activity activity); void onActivityStopped(Activity activity); void onActivitySaveInstanceState(Activity activity, Bundle outState); void onActivityDestroyed(Activity activity); }
三. Application 相关示例
1. 自定义 Application 基本使用
(1) 创建 自定义 Application
创建 Application : 创建一个类, 继承android.app.Application 类, 实现最基本的 onCreate() 方法即可;
-- 示例 :
package cn.org.octopus.application; import android.app.Application; public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); } }
(2) 注册 Application
在 Manifest.xml 中注册 Application : 在 <application> 标签中添加 android:name 属性, 属性值就是 自定义 MyApplication 路径;
-- 示例 :
<application android:name="cn.org.octopus.application.MyApplication" >
2. 保存崩溃日志到文件
(1)UncaughtExceptionHandler 简介
UncaughtExceptionHandler 未捕获异常处理类简介 :
-- 线程相关 : 每个线程都有一个未捕获异常处理类;
使用自定义UncaughtExceptionHandler 类代替 线程默认的UncaughtExceptionHandler 类 :
/* * Android 中每个线程都有其指定的 未捕获异常处理类 UncaughtExceptionHandler * 这里我们将该线程的异常处理类获取, 将其赋予本类中的成员变量, 将本类设置为线程默认的 未捕获异常处理类 * 这样就相当与在 UncaughtExceptionHandler 的外层包装了一层, 我们可以对未捕获的异常信息进行任何操作 */ //获取系统默认的UncaughtException处理器 mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); //设置该CrashHandler为程序的默认处理器 Thread.setDefaultUncaughtExceptionHandler(this);
函数驱动动力 :
-- 回调方法 : 当出现了未捕获异常时, 在崩溃前会回调uncaughtException() 方法, 该方法驱动其它方法运行;
-- 详细方法 :public void uncaughtException(Thread thread, Throwable ex);
-- 重写方法 : 在方法中使用 用户自行处理 Throwable ex 抛出的异常, 如果用户没有处理, 使用默认的异常处理器;
if (!handleException(ex) && mDefaultHandler != null) { //如果用户没有处理则让系统默认的异常处理器来处理 mDefaultHandler.uncaughtException(thread, ex); }
(2) 收集相关参数信息
获取设备信息, 异常信息 :Field[] fields = Build.class.getDeclaredFields();
-- 将获取的信息转为字符串 :
/* * 该字段封装了很多信息 * 包括 : 设备信息 异常信息等 */ Field[] fields = Build.class.getDeclaredFields(); for (Field field : fields) { try { field.setAccessible(true); infos.put(field.getName(), field.get(null).toString()); Log.d(TAG, field.getName() + " : " + field.get(null)); } catch (Exception e) { Log.e(TAG, "an error occured when collect crash info", e); } }
(3) 在 Application 中注册该类
Application 中注册 : 具体内容请详看代码;
//注册异常日志处理类 CrashHandler crashHandler = CrashHandler.getInstance(); //初始化异常日志处理类 crashHandler.init(getApplicationContext());
3. 监听 Activity 生命周期
(1) 自定义ActivityLifecycleCallbacks 接口实现类
自定义ActivityLifecycleCallbacks类 :
/** * Activity 生命周期监听 * @author octopus * */ class MyActivityLifecycleCallbacks implements ActivityLifecycleCallbacks{ @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { Log.i(TAG_ACTIVITY_LIFE, activity.getClass().getName() + " : onActivityCreated"); } @Override public void onActivityStarted(Activity activity) { Log.i(TAG_ACTIVITY_LIFE, activity.getClass().getName() + " : onActivityStarted"); } @Override public void onActivityResumed(Activity activity) { Log.i(TAG_ACTIVITY_LIFE, activity.getClass().getName() + " : onActivityResumed"); } @Override public void onActivityPaused(Activity activity) { Log.i(TAG_ACTIVITY_LIFE, activity.getClass().getName() + " : onActivityPaused"); } @Override public void onActivityStopped(Activity activity) { Log.i(TAG_ACTIVITY_LIFE, activity.getClass().getName() + " : onActivityStopped"); } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { Log.i(TAG_ACTIVITY_LIFE, activity.getClass().getName() + " : onActivitySaveInstanceState"); } @Override public void onActivityDestroyed(Activity activity) { Log.i(TAG_ACTIVITY_LIFE, activity.getClass().getName() + " : onActivityDestroyed"); } }
在 onCreate() 方法中注册该类 :
//注册 Activity 声明周期监听器 registerActivityLifecycleCallbacks(new MyActivityLifecycleCallbacks());
(2) 执行效果
执行效果 :
octopus@octopus:~$ adb logcat | grep cn.org.octopus.application.activity.life I/cn.org.octopus.application.activity.life(12217): cn.org.octopus.application.MainActivity : onActivityCreated I/cn.org.octopus.application.activity.life(12217): cn.org.octopus.application.MainActivity : onActivityStarted I/cn.org.octopus.application.activity.life(12217): cn.org.octopus.application.MainActivity : onActivityResumed I/cn.org.octopus.application.activity.life(12217): cn.org.octopus.application.MainActivity : onActivityPaused I/cn.org.octopus.application.activity.life(12217): cn.org.octopus.application.MainActivity : onActivityStopped I/cn.org.octopus.application.activity.life(12217): cn.org.octopus.application.MainActivity : onActivityDestroyed
博客地址:http://blog.csdn.net/shulianghan/article/details/40737419
代码下载:Android 应用 Application 经典用法;
--Github:https://github.com/han1202012/ApplicationDemo
--CSDN:http://download.csdn.net/detail/han1202012/8127247
相关推荐
在Android系统中,每个应用程序都默认关联一个`Application`类,它是程序的全局上下文,负责初始化全局变量、设置全局配置等。然而,在某些特定情况下,我们可能需要创建多个`Application`来处理不同的任务或者使用...
### 三、Android应用框架部分 - **常用框架部分**: - View组件:用于构建用户界面。 - ContentProviders:用于跨程序访问数据。 - ResourceManger:资源管理器。 - NotificationManger:通知管理器。 - ...
在Android应用开发中,为了...总之,Android应用开发中使用第三方字体可以极大地丰富UI设计,但同时也需要注意性能、兼容性和版权等问题。通过合理的方式引入和管理自定义字体,可以为用户提供更加美观和个性化的体验。
2. JSON解析:Android应用程序经常需要与服务器交换JSON格式的数据。书中介绍了使用Gson和Jackson库进行JSON序列化和反序列化的技巧,以及如何手动解析JSON对象和数组。 3. 网络状态管理:Android设备的网络环境...
《Professional Android 4 Application Development》是一本针对Android应用开发的专业指南,由Rob Miles撰写,是Android开发者中的经典之作。这本书全面覆盖了Android 4(Ice Cream Sandwich)版本的应用开发技术,...
首先,我们要明白`Application`类是Android应用程序的基类,它在应用启动时最先被创建,并在整个应用生命周期内存在。我们可以通过重写`Application`类的方法,添加一些全局的初始化或清理操作。 **1. 创建自定义...
在Android应用开发中,开发者需要掌握一系列技术和工具来构建功能丰富的移动应用程序。API(Application Programming Interface)是Android系统的核心组成部分,它提供了与操作系统交互的接口,使得开发者可以调用...
"Android应用开发期末考试题" Android 应用开发是指使用 Android 操作系统和开发工具创建移动应用程序的过程。该过程涉及到 Android 平台的架构、Android SDK 的使用、应用程序的设计和实现、调试和测试等多个方面...
在Android应用开发中,"Android-Application被回收引发空指针异常分析(消灭全局变量)"是一个常见的问题,尤其对于新手开发者来说,可能会遇到这样的困惑。这篇文章主要探讨了当Application对象被系统回收后,如何...
Android 应用开发期末考试题 本资源摘要信息总结了 Android 应用开发期末考试题的主要知识点,涵盖了 Android 开发基础知识、Android SDK、Android 应用程序结构、Android 底层库、Android 应用程序开发等方面的...
[Addison-Wesley Professional] Android 应用开发指南 核心技术 第4版 (英文版) [Addison-Wesley Professional] Introduction to Android Application Development Android Essentials 4th Edition (E-Book) ☆ ...
* 创建新项目,选择 Android 的 Application Module * 设置 Project SDK,选择所需的 Android 版本 知识点二: Android 项目结构和文件说明 * res/layout/main.xml:App 主窗体布局文件,定义应用程序的界面布局 *...
《Android应用开发揭秘》内容全面,不仅详细讲解了Android框架、Android组件、用户界面开发、游戏开发、数据存储、多媒体开发和网络开发等基础知识,而且还深入阐述了传感器、语音识别、桌面组件开发、Android游戏...
1. **Android SDK和环境设置**:书中详细介绍了如何下载和安装Android SDK,配置开发环境,以及使用Eclipse集成开发环境(IDE)进行Android应用开发。 2. **Android架构与组件**:讲解了Android操作系统的核心组成...
《Android应用开发36计》由高焕堂大师编著,是Android开发领域的经典教材,为初学者提供了全面深入的学习资源。本书不仅介绍了Android应用框架的原理与设计,还提供了丰富的编程技巧,覆盖了Android 1.0版本,尽管...
《专业Android应用开发》是Android开发领域的一本权威指南,旨在帮助读者从初学者到熟练开发者,逐步掌握Android应用程序的设计、实现与优化技巧。这本书详细介绍了Android开发的各个方面,包括环境搭建、UI设计、...
通过这个例子,我们可以更好地理解 Android 系统的桌面应用程序,并开发出自己的桌面应用程序。 延伸阅读 * Android 官方文档:Launcher 开发指南 * Android 官方文档:Intent 和 Intent Filter * Android 官方...