机器人不会从堆栈中杀死活动时,内存不足堆栈、机器人、内存不足

2023-09-12 22:19:07 作者:Estelle.星辰

我们一直在开发有下降的仪表板下降,使用户在整个应用程序导航的应用程序。导航是不是很标准,因为这个菜单可以从几乎每一个活动进行访问。 玩了一会儿使用菜单开启活动后,堆栈开始成长和壮大。

所有这些活动包括列表视图与几个imageviews里面,他们采取3MB左右各。如果用户玩不够,在栈上创建了超过25项活动,这是发生了什么:

在内存不足的错误被抛出(堆增大,直到有没有更多的堆)。 在一个对话框显示,由于异常(不幸的是,活性%%已停止。) 其中outofmemerror被抛出的活动就结束了。 所有堆栈中的活动完成后,但历史上被保持,因此,其能够备份和每个活动由OS重新automaticall。

我期待系统杀死在堆栈中的最古老的活动自动BEFRORE的OutOfMemoryError异常被抛出......

只是可以肯定的操作系统不杀生老活动,我创建了一个测试应用程序,分配每次1MB。你猜怎么着:该行为是相同的,outofmemerror被抛出:

现在的问题是:我们如何才能知道Android操作系统,这是允许的,如果需要的,所以我们没有得到解除分配活动和资源不幸的是,你的活动已停止。对话?

概念验证

    包com.gaspar.memorytest; 

进口android.app.Activity; 进口android.content.Intent; 进口android.os.Bundle; 进口android.view.View; 进口android.view.View.OnClickListener; 进口android.widget.Button; 公共类MemoryTestActivity延伸活动{     / **第一次创建活动时调用。 * /     私人字节[] MDATA;     @覆盖     公共无效的onCreate(包savedInstanceState){         super.onCreate(savedInstanceState);         的setContentView(R.layout.main1);         ((按钮)findViewById(R.id.button))。setOnClickListener(新OnClickListener(){             @覆盖             公共无效的onClick(视图v){                 // TODO自动生成方法存根                 意图I =新的意图(MemoryTestActivity.this,MemoryTestActivity.class);                 startActivity(ⅰ);             }         });         MDATA =新的字节[1 * 1024 * 1024];     } }

解决方案   

我期待系统杀死在堆栈中自动BEFRORE的OutOfMemoryError异常被抛出最古老的活动

Android不这样做。 Android的终止进程以释放系统内存为其他进程。它并不涉足与内部应用程序的内存使用情况以类似的方式。

  99美元AI计算机来了 一文看尽英伟达昨夜大批硬核新品

我们如何才能知道Android操作系统,这是允许的,如果需要的,所以我们没有得到解除分配活动和资源不幸的是,你的活动已停止。对话?

您不能。

相反,你需要设计你的应用程序使用较少的活动,或每项活动使用更少的资源。例如,你可以回收通过FLAG_ACTIVITY_REORDER_TO_FRONT,或(如托恩基斯特先生指出的),您可以完成()手动活动吧。

  

打了使用菜单在打开的活动后,堆栈开始成长和壮大。

您或许应该使用 FLAG_ACTIVITY_REORDER_TO_FRONT 对这些菜单项,这样你在任务使现有的活动向前,而不是每次都创建新的。

We've been developing an application that has a drop down dashboard that allows the users to navigate throughout the app. The navigation is not very standard since this menu can be accessed from almost every activity. After playing for a while opening activities using the menu, the stack starts to grow and grow.

All these activities contain listviews with several imageviews inside, and they take around 3mb each. If the user plays enough and creates more than 25 activities on the stack this is what happens:

Out of memory error is thrown (Heap is increased till there's no more heap). A dialog is shown due to the exception (Unfortunately, %activity% has stopped.) The activity where the outofmemerror was thrown is finished. All the activities in the stack are finished, but the history is kept, so its possible to backup and each activity is recreated automaticall by the OS.

I was expecting the system to kill the oldest activities in the stack automatically BEFRORE the OutOfMemoryError was thrown...

Just to be sure the OS is not killing old activities, I created a test app that allocates 1mb each time. Guess what: The behavior is the same and outofmemerror is thrown:

The question is: How can we tell the Android OS that it is allowed to deallocate activities and its resources if needed so we don't get the "Unfortunately, your activity has stopped." dialog?

Proof of concept

    package com.gaspar.memorytest;

import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MemoryTestActivity extends Activity { /** Called when the activity is first created. */ private byte[] mData; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main1); ((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Intent i = new Intent(MemoryTestActivity.this, MemoryTestActivity.class); startActivity(i); } }); mData = new byte[1*1024*1024]; } }

解决方案

I was expecting the system to kill the oldest activities in the stack automatically BEFRORE the OutOfMemoryError was thrown

Android does not do this. Android terminates processes to free up system memory for other processes. It does not get involved with intra-app memory usage in a similar fashion.

How can we tell the Android OS that it is allowed to deallocate activities and its resources if needed so we don't get the "Unfortunately, your activity has stopped." dialog?

You can't.

Instead, you need to design your application to use fewer activities, or use fewer resources per activity. For example, you can "recycle" existing activity instances via FLAG_ACTIVITY_REORDER_TO_FRONT, or (as Mr. Tornquist pointed out), you can finish() activities manually yourself.

After playing for a while opening activities using the menu, the stack starts to grow and grow.

You should probably be using FLAG_ACTIVITY_REORDER_TO_FRONT on these menu items, so that you bring the existing activity forward in the task, rather than creating new ones each time.

 
精彩推荐