- Application 简单的解析
- 实际的运用
在实际的运用中我们总是将 Application 当做一个工具类使用,去传递一些全局变量等,但一般都是一些基本的数据类型 String、int 之类,
这次试着借助 Application 来全局的传递一些复杂的数据
先推荐 郭霖大神 的 Android Context 完全解析,讲了一些之前没注意的细节
Application 解析
Application的特点是,其生命周期等于程序的生命周期,它是全局单例的,所以常用该类来传递、存储数据。
实际上,当程序启动时系统会创建一个 application对象,来存储系统的信息。
相对于用 intent 传递数据,它的好处是对数据的类型和大小限制比较小。
比如我们可以在用 LruCache 缓存了图片之后,把 cache 对象传到另一个
activity。
但是用application也要小心,很可能因为存储了不该存储的数据和对象导致内存的泄露。
使用该类一般采用继承的方式。
1 新建类并继承。
2 在配置文件 AndroidManifest.xml 中,标签中,添加/修改 name
属性。继承Application
public class MyApplication extends Application{
private static MyApplication mMyApplication ;
private String StartScreenUrl="";
@Override
public void onCreate() {
super.onCreate();
mKaleApplication = this;
}
public static MyApplication getApplication(){
return mMyApplication;
}
public String getStartScreenUrl() {
return StartScreenUrl;
}
public void setStartScreenUrl(String a) {
this.StartScreenUrl = a;
}
}
- 修改AndroidManifest.xml
< application
android:name=".MyApplication"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme.custom">
获取 Application / Context 对象及静态变量
Context 的 getApplicationContext() 或者 Activity 的 getApplication()。
//在 Activity 中获取 MyApplication 实例
MyApplication application = (MyApplication) getApplication();
//在其他的地方获取 MyApplication 实例
MyApplication application =(MyApplication) context.getApplicationContext();
//在重写了 MyApplication 的 getApplication() 之后
MyApplication application = MyApplication.getApplication();
//还可以在任何地方获取到 context
Context context = MyApplication.getApplication();
//获取在 Application 初始化的静态变量
String StartScreenUrl = application.getStartScreenUrl();
实际的运用
上面已经展示了重写了 Application 后,初始化全局变量及在全局范围内获取变量的方法,但这样方法比较适合传递一些简单的对象,对于复杂的数据还是有些乏力。
但我们可以结合 HashMap 来传递数据:
- 传递数据的具体操作:
在 Application 中创建一个 HashMap ,以字符串为索引,这样我们传递的时候只要传递对应的索引的字符串就可以根据这个字符串在 HashMap 中取出这个对象了。
public class MyApplication extends Application {
private static MyApplication mApplication;
private static HashMap map;
@Override
public void onCreate() {
super.onCreate();
Stetho.initializeWithDefaults(this);
mApplication = this;
}
public static dataCache getCacheMap() {
if (map == null){
map = new dataCache();
}
return cacheMap;
}
public static MyApplication getApplication(){
return mApplication;
}
}
那么在一个获取数据的 Activity 中存入数据:
@Override
public void onSuccess(News data) {
MyApplication application = MyApplication.getApplication();
HashMap map = application.getCacheMap();
map.put("News_d",data);
}
就可以在另一个任意的地方根据"News_d"
这个 key 获取到这里的数据 data:
MyApplication application = MyApplication.getApplication();
HashMap map = application.getCacheMap();
News data = map.get("News_d");
这里的 key 是我手动设置的,在实际过程中往往是数据的 id,一般都是 int 或者 String 类型的数据,我们只要传递这个 key 就可以从 Application 的 HashMap 中获取我们的数据。
- 要注意的地方
1、首先要注意存入的数据,是否会导致内存的泄露。
比如把一个 Activity 被 GC 所回收的时候,如果 HashMap 中存有一个 View 的实例,并且这个 View 持有了这个 Activity 的 Context 导致 Activity 不能被回收,就会出现内存的泄露。
所以可以在数据传递完成后,手动 remove 相应的数据
2、注意保持在 Application 的生命周期和 app 的周期是一致的,在内存紧张的时候如果 app 被回收了, Application 保存的数据就同样被回收
说到底,这种方法适用于临时的传递数据,而对于保存数据是比较乏力的,使用的时候应当分清楚场合,避免丢失数据或引起内存的泄露。
文档
贴一些看起来比较厉害的方法:
/*
* Called by the system when the device configuration changes while your component is running.
* Note that, unlike activities, other components are never restarted when
* a configuration changes: they must always deal with the results of the
* change, such as by re-retrieving resources.
* 配置改变时触发这个方法。
*/
void onConfigurationChanged();
/*
* Called when the application is starting, before any activity, service, or
* receiver objects (excluding content providers) 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().
* 在启动所有(第一个)activity之前执行,这个没问题。
* 但注意的是这里执行的东西如果耗费很多时间,相当于影响启动的速度。
*/
void onCreate ();
//当后台程序已终止,资源还匮乏时会调用这个方法。在这个方法里面释放资源。
void onLowMemory()
//当终止利用程序对象时调用,不一定被调用。
void onTerminate