Android内存泄漏,vector 内存分配策略的几种策略

拒绝访问 | www.colabug.com | 百度云加速
请打开cookies.
此网站 (www.colabug.com) 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(427d92fffaa34370-ua98).
重新安装浏览器,或使用别的浏览器没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!&nbsp>&nbsp
&nbsp>&nbsp
&nbsp>&nbsp
Android性能优化-内存泄漏(上)
摘要:为什么要做性能优化?手机性能越来越好,不用纠结这些细微的性能?Android每一个应用都是运行的独立的Dalivk虚拟机,根据不同的手机分配的可用内存可能只有(32M、64M等),所谓的4GB、6GB运行内存其实对于我们的应用不是可以任意索取优秀的算法与效率低下的算法之间的运行效率要远远超过计算机硬件的的发展,虽然手机单核、双核到4核、8核的发展,但性能优化任然不可忽略手机应用一般使用的周期比较短,用完就关了。不像服务器应用要长年累月运行,似乎影响不大?现在一般的用户都不会重
为什么要做性能优化?
手机性能越来越好,不用纠结这些细微的性能?
Android每一个应用都是运行的独立的Dalivk虚拟机,根据不同的手机分配的可用内存可能只有(32M、64M等),所谓的4GB、6GB运行内存其实对于我们的应用不是可以任意索取
优秀的算法与效率低下的算法之间的运行效率要远远超过计算机硬件的的发展,虽然手机单核、双核到4核、8核的发展,但性能优化任然不可忽略
手机应用一般使用的周期比较短,用完就关了。不像服务器应用要长年累月运行,似乎影响不大?
现在一般的用户都不会重启手机,可能一个月都不会重启。像微信这样的APP,每天都在使用。如果一旦发生内存泄漏,那么可能一点一点的累积,程序就会出现OOM。
等应用出现卡顿、发烫等,再来关注性能优化?
似乎是没错的。现在一般我们也都是等出现问题了再来找原因。但是学好性能优化的目的不仅仅如此,我们在编码阶段就应该从源头来杜绝一些坑,这样的成本比后期再来寻找原因要少得多
所以为了我们的应用的健壮性、有良好的用户体验。性能优化技术,需要我们用心去研究和应用。
什么是内存泄漏?
JVM内存管理
Java采用GC进行内存管理。深入的JVM内存管理知识,推荐《深入理解Java虚拟机》。关于内存泄漏我们要知道,JVM内存分配的几种策略。
静态的存储区,内存在程序编译的时候就已经分配好了,这块内存在程序整个运行期间都一直存在,它主要存放静态数据、全局的static数据和一些常量。
在执行方法时,方法一些内部变量的存储都可以放在栈上面创建,方法执行结束的时候这些存储单元就会自动被注释掉。栈 内存包括分配的运算速度很快,因为内在在处理器里面。当然容量有限,并且栈式一块连续的内存区域,大小是由操作系统决定的,他先进后 出,进出完成不会产生碎片,运行效率高且稳定
也叫动态内存 。我们通常使用new 来申请分配一个内存。这里也是我们讨论内存泄漏优化的关键存储区。GC会根据内存的使用情况,对堆内存里的垃圾内存进行回收。堆内存是一块不连续的内存区域,如果频繁地new/remove会造成大量的内存碎片,GC频繁的回收,导致内存抖动,这也会消耗我们应用的性能
我们知道可以调用 System.gc();进行内存回收,但是GC不一定会执行。面对GC的机制,我们是否无能为力?其实我们可以通过声明一些引用标记来让GC更好对内存进行回收。
StrongReference (强引用)
任何时候GC是不能回收他的,哪怕内存不足时,系统会直接抛出异常OutOfMemoryError,也不会去回收
SoftReference (软引用)
当内存足够时不会回收这种引用类型的对象,只有当内存不够用时才会回收
内存不足,进行GC的时候
WeakReference (弱引用)
GC一运行就会把给回收了
PhantomReference (虚引用)
如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收
任何时候都有可能
开发时,为了防止内存溢出,处理一些比较占用内存并且生命周期长的对象时,可以尽量使用软引用和弱引用。
成员变量全部存储在堆中(包括基本数据类型,引用及引用的对象实体),因为他们属于类,类对象最终还是要被new出来的
局部变量的基本数据类型和引用存在栈中,应用的对象实体存储在堆中。因为它们属于方法当中的变量,生命周期会随着方法一起结束
内存泄漏的定义
当一个对象已经不需要使用了,本该被回收时,而有另外一个正在使用的对象持有它的引用,从而导致了对象不能被GC回收。这种导致了本该被回收的对象不能被回收而停留在堆内存中,就产生了内存泄漏
内存泄漏与内存溢出的区别
内存泄漏(Memory Leak) 进程中某些对象已经没有使用的价值了,但是他们却还可以直接或间接地被引用到GC Root导致无法回收。当内存泄漏过多的时候,再加上应用本身占用的内存,日积月累最终就会导致内存溢出OOM
内存溢出(OOM) 当 应用的heap资源超过了Dalvik虚拟机分配的内存就会内存溢出
内存泄漏带来的影响
应用卡顿 泄漏的内存影响了GC的内存分配,过多的内存泄漏会影响应用的执行效率
应用异常(OOM) 过多的内存泄漏,最终会导致 Dalvik分配的内存,出现OOM
Android开发常见的内存泄漏
单例造成的内存泄漏
当调用getInstance时,如果传入的context是Activity的context。只要这个单例没有被释放,那么这个Activity也不会被释放一直到进程退出才会释放。
public class CommUtil {
private static CommU
private CommUtil(Context context){
this.context =
public static CommUtil getInstance(Context mcontext){
if(instance == null){
instance = new CommUtil(mcontext);
能使用Application的Context就不要使用Activity的Content,Application的生命周期伴随着整个进程的周期
非静态内部类创建静态实例造成的内存泄漏
private static TestResource mResource =
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(mManager == null){
mManager = new TestResource();
class TestResource {
将非静态内部类修改为静态内部类。(静态内部类不会隐式持有外部类)
Handler造成的内存泄漏
mHandler是Handler的非静态匿名内部类的实例,所以它持有外部类Activity的引用,我们知道消息队列是在一个Looper线程中不断轮询处理消息,那么当这个Activity退出时消息队列中还有未处理的消息或者正在处理消息,而消息队列中的Message持有mHandler实例的引用,mHandler又持有Activity的引用,所以导致该Activity的内存资源无法及时回收,引发内存泄漏。
private MyHandler mHandler = new MyHandler(this);
private TextView mTextV
private static class MyHandler extends Handler {
private WeakReference&Context&
public MyHandler(Context context) {
reference = new WeakReference&&(context);
public void handleMessage(Message msg) {
MainActivity activity = (MainActivity) reference.get();
if(activity != null){
activity.mTextView.setText(&&);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textview);
loadData();
private void loadData() {
Message message = Message.obtain();
mHandler.sendMessage(message);
创建一个静态Handler内部类,然后对Handler持有的对象使用弱引用,这样在回收时也可以回收Handler持有的对象,这样虽然避免了Activity泄漏,不过Looper线程的消息队列中还是可能会有待处理的消息,所以我们在Activity的Destroy时或者Stop时应该移除消息队列中的消息
private MyHandler mHandler = new MyHandler(this);
private TextView mTextV
private static class MyHandler extends Handler {
private WeakReference&Context&
public MyHandler(Context context) {
reference = new WeakReference&&(context);
public void handleMessage(Message msg) {
MainActivity activity = (MainActivity) reference.get();
if(activity != null){
activity.mTextView.setText(&&);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView)findViewById(R.id.textview);
loadData();
private void loadData() {
//...request
Message message = Message.obtain();
mHandler.sendMessage(message);
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
线程造成的内存泄漏
异步任务和Runnable都是一个匿名内部类,因此它们对当前Activity都有一个隐式引用。如果Activity在销毁之前,任务还未完成, 那么将导致Activity的内存资源无法回收,造成内存泄漏
new AsyncTask&Void, Void, Void&() {
protected Void doInBackground(Void... params) {
SystemClock.sleep(10000);
}.execute();
new Thread(new Runnable() {
public void run() {
SystemClock.sleep(10000);
}).start();
使用 静态内部类,避免了Activity的内存资源泄漏,当然在Activity销毁时候也应该取消相应的任务AsyncTask::cancel(),避免任务在后台执行浪费资源
static class MyAsyncTask extends AsyncTask&Void, Void, Void& {
private WeakReference&Context& weakR
public MyAsyncTask(Context context) {
weakReference = new WeakReference&&(context);
protected Void doInBackground(Void... params) {
SystemClock.sleep(10000);
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
MainActivity activity = (MainActivity) weakReference.get();
if (activity != null) {
static class MyRunnable implements Runnable{
public void run() {
SystemClock.sleep(10000);
//——————
new Thread(new MyRunnable()).start();
new MyAsyncTask(this).execute();
资源未关闭造成的内存泄漏
对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏
在Activity销毁时及时关闭或者注销
使用了静态的Activity和View
void setStaticView() {
view = findViewById(R.id.sv_button);
View svButton = findViewById(R.id.sv_button);
svButton.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
setStaticView();
nextActivity();
void setStaticActivity() {
activity =
View saButton = findViewById(R.id.sa_button);
saButton.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
setStaticActivity();
nextActivity();
应该及时将静态的应用 置为null,而且一般不建议将View及Activity设置为静态
注册了系统的服务,但onDestory未注销
SensorManager sensorManager = getSystemService(SENSOR_SERVICE);
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL);
sensorManager.registerListener(this,sensor,SensorManager.SENSOR_DELAY_FASTEST);
//不需要用的时候记得移除监听
sensorManager.unregisterListener(listener);
不需要用的监听未移除会发生内存泄露
//add监听,放到集合里面
tv.getViewTreeObserver().addOnWindowFocusChangeListener(new ViewTreeObserver.OnWindowFocusChangeListener() {
public void onWindowFocusChanged(boolean b) {
//监听view的加载,view加载出来的时候,计算他的宽高等。
//计算完后,一定要移除这个监听
tv.getViewTreeObserver().removeOnWindowFocusChangeListener(this);
tv.setOnClickListener();//监听执行完回收对象,不用考虑内存泄漏tv.getViewTreeObserver().addOnWindowFocusChangeListene,add监听,放到集合里面,需要考虑内存泄漏
下一篇将介绍如何进行内存泄漏的分析
以上是的内容,更多
的内容,请您使用右上方搜索功能获取相关信息。
若你要投稿、删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内给你回复。
云服务器 ECS
可弹性伸缩、安全稳定、简单易用
&40.8元/月起
预测未发生的攻击
&24元/月起
为您提供0门槛上云实践机会
你可能还喜欢
你可能感兴趣
阿里云教程中心为您免费提供
Android性能优化-内存泄漏(上)相关信息,包括
的信息,所有Android性能优化-内存泄漏(上)相关内容均不代表阿里云的意见!投稿删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内答复
售前咨询热线
支持与服务
资源和社区
关注阿里云
InternationalAndroid内存泄漏 ——检测、解决和避免 - 简书
Android内存泄漏 ——检测、解决和避免
作为开发人员,在我们的日常开发中,为了构建更好的应用程序,我们需要考虑很多事情以保证应用运行在正轨上,其中之一是要确保我们的应用程序不会崩溃。应用崩溃的一个常见原因是内存泄漏。这方面的问题可以以各种形式表现出来。在大多数情况下,我们看到内存使用率稳步上升,直到应用程序不能分配更多的资源,并不可避免地崩溃。在Java中这往往导致一个OutOfMemoryException异常被抛出。在某些罕见的情况下,泄露的类甚至可以逗留很长时间来接收已注册的回调,这会导致一些非常奇怪的错误,并往往抛出臭名昭著的IllegalStateException异常。
为了帮助他人在代码分析上减少花费时间,我将介绍内存泄漏的几个例子,阐述在Android Studio中如何检查它们,当然最重要的是如何将其解决。
在这篇文章中的代码示例的目的是为了促进大家对内存管理有更深的了解,特别是在java。其通用的体系结构,线程管理和代码示例的 HTTP 请求处理在真实的生产环境并不是理想的,这些示例仅仅为了说明一个问题:在Android中,内存泄漏是一件要考虑的事情。
监听器注册
这真的不应该是个问题,但我经常看到各种注册方法的调用,但他们对应的注销方法却无处可寻。这是泄漏的潜在来源,因为这些方法明确设计成互相抵消。如果没有调用注销方法,被引用的对象已经被终止后,监听实例可能会持有该对象很长的时间,从而导致泄漏内存。在Android中,如果该对象是一个Activity对象,是特别麻烦的,因为他们往往拥有大量的数据。让我告诉你,可能是什么样子。
public class LeaksActivity extends Activity implements LocationListener {
private LocationManager locationM
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leaks);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
TimeUnit.MINUTES.toMillis(5), 100, this);
// Listener implementation omitted
在这个例子中,我们让Android的 通知我们位置更新。我们所需要做的就是获取系统服务本身和设置一个回调来接收更新。在这里,我们在Activity中实现了位置监听接口,这意味着LocationManager将持有该Activity的引用。现在,如果该设备被旋转,新的Activity将被创建并取代已经注册位置更新接口的旧的Activity。由于系统服务存活时间肯定比任何Activity都要长,LocationManager仍然持有以前的Activity的引用,这使GC不可能回收依赖于以前的Activity的资源,从而导致内存泄漏。如果反复旋转设备,将导致大量的不可回收的Activity填满内存,最终导致OutOfMemoryException异常。
但为了解决内存泄漏,我们首先必须要能够找到它。幸运的是,Android Studio有一个叫做 Android Monitor的内置工具,我们可以用它来 观察除应用内存使用情况。我们需要做的仅仅是打开Android Monitor 并转到对应tab,看看使用了多少内存和内存实时分配情况。
1-3R36AJUjtdBArkIxPuED3g.png
任何导致资源分配的交互都在这里反映出来,使之成为跟踪应用程序的资源使用情况的理想场所。为了找到内存泄露,当我们怀疑在某个时间点内存被泄露时,我们需要知道在该时间点包含了那些内存。对于这个特殊的例子,我们所要做的就是启动我们的应用程序,然后旋转设备一次,然后调用Dump Java Heap操作(在Memory的旁边,从左边数起第三个图标)。这将生成一个HPROF文件,其中包含我们调用该操作时的一个内存快照。几秒钟后,Android Studio 会自动打开该文件,给我们更易于分析内存的直观表示。
我不会去深入有关如何分析巨大的内存堆。相反,我会把你的注意力引导到 Analyzer Tasks(下面截图中的右上角)。为了检测上面的例子中引入的内存泄漏,你所需要做的检测是检查泄露的Activity(Detect Leaked Activities),点击播放按钮然后在Analysis Results下面就会显示泄露的Activity情况。
Paste_Image.png
如果我们选中泄露的Activity,可以得到一个引用树,该引用树可以检测持有该Activity的引用。通过寻找深度为零的实例,我们发现位置管理器中的实例mListener,是我们的Activity不能被GC回收的原因。回到我们的代码,我们可以看到,这个引用是由于我们在requestLocationsUpdates方法中设置Activity作为位置更新回调导致的。通过阅读,问题很快变得清晰,为了取消回调设置,我们简单地调用removeUpdates方法就行了。在我们的例子,因为我们注册更新是在onCreate方法,显然要注销的地方在onDestroy方法。
public class LeaksActivity extends Activity implements LocationListener {
private LocationManager locationM
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_leaks);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
TimeUnit.MINUTES.toMillis(5), 100, this);
protected void onDestroy() {
locationManager.removeUpdates(this);
super.onDestroy();
// Listener implementation omitted
重新构建程序并执行与上述相同的内存分析,无论旋转多少次设备,应该都不会导致Activity泄漏。
内部类在Java中是一个很常见的数据结构。它们很受欢迎,因为它们可以以这样的方式来定义:即只有外部类可以实例化它们。很多人可能没有意识到的是这样的类会持有外部类的隐式引用。隐式引用很容易出错,尤其是当两个类具有不同的生命周期。以下是常见的Android Activity写法。
public class AsyncActivity extends Activity {
TextView textV
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async);
textView = (TextView) findViewById(R.id.textView);
new BackgroundTask().execute();
private class BackgroundTask extends AsyncTask&Void, Void, String& {
protected String doInBackground(Void... params) {
// Do background work. Code omitted.
return "some string";
protected void onPostExecute(String result) {
textView.setText(result);
这种特殊的实现在执行上没有问题。问题是,它保留内存的时间肯定会超过必要的时间。由于BackgroundTask持有一个AsyncActivity隐式引用并运行在另一个没有取消策略的线程上,它将保留AsyncActivity在内存中的所有资源连接,直到后台线程终止运行。在HTTP请求的情况下,这可能需要很长的时间,尤其是在速度较慢的连接。
通过执行相同的步骤,如同前面的示例,并确保长时间运行的后台任务,我们最终会得到下面的分析结果。
Paste_Image.png
从上面的分析中可以看出,BackgroundTask 确实是这种内存泄漏的罪魁祸首。我们第一要务是使用静态类的实现方式来消除指向Activity的引用,但这样我们也不能直接访问 textView 了。因此我们还需要添加一个构造函数,把textView作为参数传递进来。最后,我们需要引入中所述的取消策略。考虑到所有这一切,让我们看看我们的代码最终呈现。
public class AsyncActivity extends Activity {
TextView textV
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async);
textView = (TextView) findViewById(R.id.textView);
task = new BackgroundTask(textView).execute();
protected void onDestroy() {
task.cancel(true);
super.onDestroy();
private static class BackgroundTask extends AsyncTask&Void, Void, String& {
private final TextView resultTextV
public BackgroundTask(TextView resultTextView) {
this.resultTextView = resultTextV
protected void onCancelled() {
// Cancel task. Code omitted.
protected String doInBackground(Void... params) {
// Do background work. Code omitted.
return "some string";
protected void onPostExecute(String result) {
resultTextView.setText(result);
现在,隐式引用已被消除,我们通过构造函数传递相关实例,并在合适的地方取消任务。让我们再运行分析任务,看看这种改变是否消除了内存泄漏。
Paste_Image.png
看来我们还有一些工作要做。根据前一个例子的经验,我们可以知道在引用树中高亮标注的实例导致了Activity泄露。那么这是什么回事?我们看一下它的父节点就可以发现resultTextView持有一个mContext引用,毫无疑问,它就是泄露的Activity的引用。那么如何解决这个问题?我们无法消除resultTextView绑定的context引用,因为我们需要在BackgroundTask中使用resultTextView的引用,以便更新用户界面。为了解决这个问题,一种简单的方法是使用。我们持有的resultTextView引用是强引用,具有防止GC回收的能力。相反,WeakReference不保证其引用的实例存活。当一个实例最后一个强引用被删除,GC会把其资源回收,而不管这个实例是否有弱引用。下面是使用WeakReference的最终版本:
public class AsyncActivity extends Activity {
TextView textV
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_async);
textView = (TextView) findViewById(R.id.textView);
task = new BackgroundTask(textView).execute();
protected void onDestroy() {
task.cancel(true);
super.onDestroy();
private static class BackgroundTask extends AsyncTask&Void, Void, String& {
private final WeakReference&TextView& textViewR
public BackgroundTask(TextView resultTextView) {
this.textViewReference = new WeakReference&&(resultTextView);
protected void onCancelled() {
// Cancel task. Code omitted.
protected String doInBackground(Void... params) {
// Do background work. Code omitted.
return "some string";
protected void onPostExecute(String result) {
TextView view = textViewReference.get();
if (view != null) {
view.setText(result);
请注意,在onPostExecute我们要检查空值,判断实例是否被回收。
最后,再一次运行分析器任务,确认我们的Activity不再被泄露 !
这种类型的类和内部类有同样的缺点,即他们持有外部类的引用。如同内部类,一个匿名类在Activity生命周期之外执行或在其他线程执行工作时,可能会导致内存泄漏。在这个例子中,我将使用流行的HTTP请求库执行API调用,并传递响应给对应回调。根据上面例子对Retrofit进行配置。我会在Application中持有GitHubService引用,这不是一个特别好的设计,这仅仅服务于这个例子的目的。
public class ListenerActivity extends Activity {
TextView textV
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listener);
textView = (TextView) findViewById(R.id.textView);
GitHubService service = ((LeaksApplication) getApplication()).getService();
service.listRepos("google")
.enqueue(new Callback&List&Repo&&() {
public void onResponse(Call&List&Repo&& call,
Response&List&Repo&& response) {
int numberOfRepos = response.body().size();
textView.setText(String.valueOf(numberOfRepos));
public void onFailure(Call&List&Repo&& call, Throwable t) {
// Code omitted.
这是常见的解决方案,不应该导致任何泄漏。但是,如果我们在慢速连接中执行这个例子,分析结果会有所不同。请记住,直到该线程终止,该Activity会一直被持有,就像在内部类的例子。
Paste_Image.png
根据在内部类的例子中同样的推理,我们得出一个结论:匿名回调类是内存泄漏的原因。然而,正如内部类的例子,此代码包含两个问题。首先,请求没有取消策略。其次,需要消除对Activity的隐式引用。明显的解决办法:我们在内部类的例子做了同样的事情。
public class ListenerActivity extends Activity {
TextView textV
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listener);
textView = (TextView) findViewById(R.id.textView);
GitHubService service = ((LeaksApplication) getApplication()).getService();
call = service.listRepos("google");
call.enqueue(new RepoCallback(textView));
protected void onDestroy() {
call.cancel();
super.onDestroy();
private static class RepoCallback implements Callback&List&Repo&& {
private final WeakReference&TextView& resultTextV
public RepoCallback(TextView resultTextView) {
this.resultTextView = new WeakReference&&(resultTextView);
public void onResponse(Call&List&Repo&& call,
Response&List&Repo&& response) {
TextView view = resultTextView.get();
if (view != null) {
int numberOfRepos = response.body().size();
view.setText(String.valueOf(numberOfRepos));
public void onFailure(Call&List&Repo&& call, Throwable t) {
// Code omitted.
根据上述解决方案,运行分析任务,将不会再有Activity的泄露。
后台任务独立于Activity的生命周期运行是一件麻烦事。再加上需要协调用户界面和各种后台任务之间的数据流,如果你不小心,那将是一个灾难。所以要知道你在做什么,以及你的代码是否对性能有影响。这些基本准则是处理Activity的良好开端:
尽量使用静态内部类。每个非静态内部类将持有一个外部类的隐式引用,这可能会导致不必要的问题。使用静态内部类代替非静态内部类,并通过弱引用存储一些必要的生命周期引用。
考虑后台服务等手段, Android提供了多种在非主线程工作的方法,如HandlerThread,IntentService和AsyncTask,它们每个都有自己的优缺点。另外,Android提供了一些机制来传递信息给主线程以更新UI。譬如,广播接收器就可以很方便实现这一点。
不要一味依赖垃圾回收器。使用具有垃圾回收功能的语言编码很容易有这样的想法:即没必要考虑内存管理。我们的示例清楚地表明,并非如此。因此,请确保你分配的资源都被预期回收。
普通程序猿
个人博客:
http://blog.adisonhyh.com/
https://github.com/adisonhuang
个人公众号:普通程序猿
用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? ... Android 获取 View 宽高的常用正确方式,避免为零 - 掘金 相信有很多...
用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? ... Android 获取 View 宽高的常用正确方式,避免为零 - 掘金相信有很多朋友...
内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题。内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC 不能回收。最近自己阅读了大量相关的文档资料,打算做个总结沉淀下来跟大家一起分享和学...
Android 内存泄漏总结 内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题。内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC 不能回收。最近自己阅读了大量相关的文档资料,打算做个...
自日开放台湾自由行以来,截止到目前一共开放了47个城市。具有以下城市户籍的居民以及在开放异地户籍办理城市的人员,均可办理自由行手续(包括台湾本岛和离岛)。 开放城市列表:北京、上海、厦门、天津、重庆、南京、广州、杭州、成都、济南、西安、福州、深圳、沈阳、郑...
LEON: 今天我们来上第五课。 昨晚你说看电影学英语,真是快乐学英语。说得对,也不全对。看电影是学英语的一部分,不是全部。 听,说,读,写是我们使用英语的几个主要方面,今天我们来学习一下怎么“听”。 在英语里面有大量单词,而要把单词说对,就要学好音标。 英文字母一共有26...
彪悍的人生不需要解释。彪悍的德国税务局“彪”起来,也够人喝一壶的。 乔姐在德国居住快30年,对德国的各种规定门清儿。又到每年退税时,前些天,乔姐的银行账户收到税务局的退税金1万欧元。10000欧元?乔姐揉揉眼睛,没错吧?没错,是一万欧元(相当于8万人民币)。 乔姐自己计算的...
我在黑夜里潜行, 不见一丝的光亮。 月亮和星子也已安眠, 不见一个出路。
把健康健美的app把玩一边后,还是出现了很多问题,说是在第一阶段体验到什么想到什么救写什么,可是应用玩多了,就陷入了审美疲劳,ui的设计、界面的设计都大差不差,没有特别突出的。对于有些应用提高到用户的需求,使用的场景进行分析还是把握不准,所以妄下结论还是不妥。所以,最近把前...}

我要回帖

更多关于 java 内存分配策略 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信