Android 中尽量不要使用静态变量,尽量不要在Applicaotion存缓存数据

前言

Android是用Java开发,其静态变量的生命周期遵守Java的设计。

我们知道静态变量是在类被load的时候分配内存的,并且存在于方法区。

当类被卸载的时候,静态变量被销毁。

那么在Android中呢?

用的Dalvik vm也是一样的。

不过Android不太突出的进程概念,所以对静态变量的生命周期就会感觉模糊,这种模糊对于值类型是无所谓的,如果是静态的对象引用,则与内存回收、内存泄漏这些问题有关,有必要加深研究和理解。

静态变量在类被加载的时候分配内存

类在什么时候被加载?

当我们启动一个app的时候,系统会创建一个进程,此进程会加载一个Dalvik VM的实例,然后代码就运行在DVM之上,类的加载和卸载,垃圾回收等事情都由DVM负责。

也就是说在进程启动的时候,类被加载,静态变量被分配内存。

静态变量在类被卸载的时候销毁

类在什么时候被卸载?

在进程结束的时候。

说明:一般情况下,所有的类都是默认的ClassLoader加载的,只要ClassLoader存在,类就不会被卸载,而默认的ClassLoader生命周期是与进程一致的,这里讨论一般情况。

Android中的进程什么时候结束

这个是Android对进程和内存管理不同于PC的核心---如果资源足够,Android不会杀掉任何进程,另一个意思是进程随时可能会被杀掉。而Android会在资源足够的时候,恢复被杀掉的进程,但Android在你恢复这个应用时并不是重启这个应用,它会创建一个新的Application对象并且启动上次用户离开时的activity以造成这个app从来没有被kill掉得假象。也就是说静态变量的值,如果不做处理,是不可靠的,可以说内存中的一切都不可靠,如果要可靠,还是保存到Nand或SD卡中去,在恢复恢复应用的时候恢复回来。

下面具体分析一下

不要往Application存缓存数据

当然这不是绝对化,只是这么建议。

在你的App中的很多地方都需要使用到数据信息,它可能是一个session token,一次费时计算的结果等等,通常为了避免Activity之间传递数据的开销,会将这些数据通过持久化来存储。

有人建议将这些数据放在Application对象中方便所有的Activity访问,这个解决方案简单、优雅并且是……完全错误的。

你如果你将数据缓存到Application对象中,那么有可能你的程序最终会由于一个NullPointerException异常而崩溃掉。

数据存在Application被gc后数据都是的demo演示

下面通过demo演示因为数据存放在application导致数据丢失的情况:

1、新建一个类MyApplication继承自Application,弄一个那么的属性设置对应的get和set方法,并且让我们的程序的清单文件的application采用我们的MyApplication2、弄三个acitivity,MainActivity有一个按钮,点击则打开FirstActivity,而Activity的onCreate方法干的事就是给MyApplicatipn的name属性set一个值,比如“Try Text”,接着就直接打开我们的SecondActivity3、SecondAcrivity直接有一个TextView控件,这个控件用于显示从MyApplication取出来的那么的值。

嗯就是这样子,正常情况下,我们进入MainActivity,点击 “打开FirstActivity” 只会就进入FirstActivity之后瞬间进入SecondActivity。SecondActivity正常显示FirstActivity给存储在MyApplication里面的值。

这个是没什么问题的。这个时候,我们按下home键,然后利用DDMS把当前app杀掉(模拟给gc回收),然后在打开app,会发现SecondActivity显示的name值变为null,数据丢失了。一旦使用这个值就报空指针。

接下来贴一些代码:

MyApplication

public class MyApplication extends Application{

@Override

public void onCreate() {

super.onCreate();

}

String name;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

MainActivity

public class MainActivity extends Activity {

private TextView mTvOpenFirst;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTvOpenFirst= (TextView) findViewById(R.id.mTvOpenFirst);

mTvOpenFirst.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Intent openFirst = new Intent(MainActivity.this,FirstActivity.class);

startActivity(openFirst);

}

});

}

}

FirstActivity

public class FirstActivity extends Activity{

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_first);

MyApplication app = (MyApplication) getApplication();

app.setName("Try Text");

startActivity(new Intent(this, SecondActivity.class));

}

}

SecondActivity

public class SecondActivity extends Activity{

private TextView mTv;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_second);

mTv= (TextView) findViewById(R.id.mTv);

MyApplication app = (MyApplication) getApplication();

mTv.setText("HELLO " + app.getName());

Log.d("fixmothod", "是否为空:" + (app.getName() == null));

// app.getName()为null,调用下面这句代码就会引发空指针

//boolean equals= app.getName().equals("123");

}

}

去掉备注的boolean equals= app.getName().equals("123");

再运行一遍就会引发报错。

另一个种情况就是不能把退出所有Activity等同于进程的退出,所以在用户点击图标启动应用的时候,以前存放于静态变量中的值,有可能还存在,因此要视具体情况给予清空操作。

在Application存缓存数据也是一样不可靠

Application其实是一个单例对象,也是放在内存中的,当进程被杀掉,缓存就全清空了,只不过Android系统会帮恢复Application,而我们存放在Application的数据自然就没有了,还是得自己处理。

不过我们可以在Application被销毁时直接退出程序。

退出程序方法请查看博客Android 杀掉App所有相关的进程,并退出应用程序(彻底杀死App)_ErwinNakajima的博客-CSDN博客_android 杀死app进程

其实Application都被销毁了,程序就应该退出的。

静态引用的对象不会被回收?

在Android之外的Java运行环境中,你只要关心进程生命周期,在进程生命周期内你可以放心地使用静态变量来保持数据。只要静态变量没有被销毁也没有置null,其对象一直被保持引用,因此不会被垃圾回收,因此单例对象在运行时不会被回收,但是Android里它随时会被系统置null。

如对此有疑问,请联系qq1164688204。

推荐Android开源项目

项目功能介绍:RxJava2和Retrofit2项目,添加自动管理token功能,添加RxJava2生命周期管理,使用App架构设计是MVP模式和MVVM模式,同时使用组件化,部分代码使用Kotlin,此项目持续维护中。

项目地址:https://gitee.com/urasaki/RxJava2AndRetrofit2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值