作者:曹莹888淑女 | 来源:互联网 | 2022-12-02 11:10
所以,我经常听到"坚持静态活动或视图,特别是在长时间运行的AsyncTask中会导致内存泄漏并导致应用程序崩溃".
但是,我无法在Android模拟器中真正证明这一点.
我究竟做错了什么?
public class MainActivity extends AppCompatActivity {
static TextView label;
static List sHolder = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewGroup vg = findViewById(R.id.blah);
for (int i=0; i<1000000; i++) {
ImageView im = new ImageView(this);
im.setImageDrawable(getApplicationContext().getDrawable(R.drawable.kitten_original));
vg.addView(im);
new MyTask(this).execute();
}
sHolder.add(this);
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
class MyTask extends AsyncTask {
Activity activity;
public MyTask(Activity activity) {
this.activity = activity;
}
@Override
protected Void doInBackground(Void... voids) {
try {
Thread.sleep(10000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
而不是每次崩溃,我的计算机只是开始滞后一点,它看起来像100 MB的垃圾收集发生.
我怎么能真正强迫应用程序崩溃?(请不要问我为什么要强制应用程序崩溃,我正在进行一些限制测试)
1> CommonsWare..:
我经常听到"保持静态活动或视图,特别是在长时间运行的AsyncTask中会导致内存泄漏并导致应用程序崩溃".
这是一个简化的解释.
但是,我无法在Android模拟器中真正证明这一点.
我怀疑这段代码没有运行.在完成循环几百次后你应该崩溃,因为AsyncTasks
你可以拥有多少排队限制,并且这个限制与内存消耗无关.
忽略百万AsyncTasks
和百万ImageViews
,你正在泄漏活动sHolder
,就像在这个样本中我通过从其布局中保持对a的static
引用泄漏活动一样Button
:
/***
Copyright (c) 2015 CommonsWare, LLC
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
by applicable law or agreed to in writing, software distributed under the
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
Covered in detail in the book _The Busy Coder's Guide to Android Development_
https://commonsware.com/Android
*/
package com.commonsware.android.button;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
public class ButtonDemoActivity extends Activity {
private static Button pleaseDoNotDoThis;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pleaseDOnotDoThis=(Button)findViewById(R.id.button1);
}
}
您可以使用LeakCanary,Android Studio的堆分析器等证明泄漏.但是,要证明泄漏,您需要运行应用程序,然后按BACK,并查看您的销毁活动不是垃圾回收.或者,您需要运行应用程序,旋转屏幕(或进行任何其他类型的配置更改),并看到您现在有两个活动实例,销毁和泄漏的实例加上当前实例.如果您只运行应用程序并且什么也不做,那么您没有泄露活动 - 虽然您有自己的静态引用,但Android也是如此,因为活动位于前台,用户可以看到它.
泄漏本身不会导致崩溃.它只是意味着你正在占用不能用于其他事情的堆空间.最终,您将获得OutOfMemoryError
一些分配.如果您想要做的就是崩溃OutOfMemoryError
,请尝试分配一些大量byte[]
(例如,1GB).
如果您特别想要测试OutOfMemoryError
泄漏活动触发的内容,则需要:
让活动分配大量的堆空间(例如,1MB byte[]
),
做一些像你的sHolder
清单,和
旋转屏幕很多,或者让自己陷入这样一种情况:大量的活动实例会被创建和销毁,但不会被垃圾收集,礼貌的你自己 sHolder