在Android Studio中使用处理会导致内存泄漏

在Android Studio中使用处理会导致内存泄漏,android,android-studio,memory-leaks,applet,processing,Android,Android Studio,Memory Leaks,Applet,Processing,请善待我,我是新来的 我通过PApplet在Android Studio中使用处理(根据此处详述的处理示例:) 在Android Studio中,我有两个活动(MainActivity和Screen2),单击MainActivity中的按钮将调用Screen2。从屏幕2,我想能够点击手机的后退按钮返回到MainActivity 好的,它确实有效…但是根据Android Profiler,我有一个内存泄漏,并且通过反复打开和关闭Screen2(最终),我得到了一个内存不足错误,应用程序崩溃 我检查

请善待我,我是新来的

我通过PApplet在Android Studio中使用处理(根据此处详述的处理示例:)

在Android Studio中,我有两个活动(MainActivity和Screen2),单击MainActivity中的按钮将调用Screen2。从屏幕2,我想能够点击手机的后退按钮返回到MainActivity

好的,它确实有效…但是根据Android Profiler,我有一个内存泄漏,并且通过反复打开和关闭Screen2(最终),我得到了一个内存不足错误,应用程序崩溃

我检查过Google、StackOverflow等,知道onStop和onDestroy方法以及活动和片段的生活方式,但我显然没有正确使用它们,因为我无法阻止泄漏(我哪里都没有,所以这里甚至没有包括这些方法)

以下是类文件的内容:

MainActivity.java

package com.example.test;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}


public void jump(View v){
   Intent i = new Intent(this, Screen2.class);
    startActivity(i);
}
}
package com.example.test;

import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import processing.android.CompatUtils;
import processing.android.PFragment;
import processing.core.PApplet;

public class Screen2 extends AppCompatActivity {

private PApplet sketch;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    FrameLayout frame = new FrameLayout(this);
    frame.setId(CompatUtils.getUniqueViewId());
    setContentView(frame, new 
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT));

    sketch = new mySketch();
    PFragment fragment = new PFragment(sketch);
    fragment.setView(frame, this);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (sketch != null) {
sketch.onRequestPermissionsResult(requestCode, permissions, rantResults);
}
}

@Override
public void onNewIntent(Intent intent) {
if (sketch != null) {
sketch.onNewIntent(intent);
}
}
}
(我通过activity_main.xml中按钮的onClick属性调用jump方法)

Screen2.java

package com.example.test;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}


public void jump(View v){
   Intent i = new Intent(this, Screen2.class);
    startActivity(i);
}
}
package com.example.test;

import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import processing.android.CompatUtils;
import processing.android.PFragment;
import processing.core.PApplet;

public class Screen2 extends AppCompatActivity {

private PApplet sketch;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    FrameLayout frame = new FrameLayout(this);
    frame.setId(CompatUtils.getUniqueViewId());
    setContentView(frame, new 
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT));

    sketch = new mySketch();
    PFragment fragment = new PFragment(sketch);
    fragment.setView(frame, this);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (sketch != null) {
sketch.onRequestPermissionsResult(requestCode, permissions, rantResults);
}
}

@Override
public void onNewIntent(Intent intent) {
if (sketch != null) {
sketch.onNewIntent(intent);
}
}
}
mySketch.java(处理文件)

Android Profiler说漏洞在Java中,所以我的感觉是,尽管Screen2活动正在关闭,但处理草图的片段没有关闭。我是否需要为此使用FragmentManager(目前我仍然无法理解),或者是否有一种简单的方法可以在Screen2活动关闭的同时关闭处理片段并正确释放内存?(我只有一个片段)

谢谢你的帮助


Simon

[对不起,我想说这些作为评论,但鉴于我目前的声誉,我不能回答,而且没有其他人回答你的问题,因为我已经分析了样本和你的代码,我将这些作为答案分享]

在研究了您的代码和“android处理”链接中提供的两个示例后,这是结论,希望能帮助您找到准确答案:

代码依赖项的更新可能有问题,或者您使用的是旧版本的依赖项,但使用的是更新的代码格式。另一件事是我不明白为什么需要更改活动,只需在主活动中实现代码,然后看看会发生什么。我的建议是,在您收集足够的处理知识之后,尝试添加更多活动并检查性能问题

通过分析这两个示例代码,它们在我的仿真器中运行顺利,并且没有产生任何错误
内存泄漏,PApplet的PFragment是内置代码,因此出错的可能性很小,但并非不可能。因此,我最好的猜测是pf片段的依赖关系可能有问题。尝试通过添加“实现文件('libs/processing core.jar')来更改依赖项,该文件可以从示例代码ex2_fragments_sv4“dir:app/libs/processing core.jar”中找到。

对不起,我也不能发表评论(Rep好的,我发现了问题。实际上有两个单独的文件

我将结束这个问题,但包括我的想法,以防它对其他人有帮助

首先,一个简单的问题:我认为上面代码中有一个(公认的小)漏洞(即1-2Mb),实际上根本不是漏洞我在Android Profiler中注意到,我使用的内存不断增加,并认为这是一个漏洞。如果我有更多的耐心并等待更长的时间,我就会看到垃圾收集器完成它的工作,并恢复我认为丢失的内存

我学到了什么?耐心的需要!不再使用的内存在Android中并不总是能立即清理干净,这并不意味着你有漏洞

现在来看更大的一个:上面的示例代码只是在一个更复杂的项目中复制一个更大的泄漏(每次我打开和关闭第二个活动时大约50Mb),涉及处理、PApplets和片段。最初我认为上面的基本代码是在以更小的规模重新创建相同的泄漏(我把它包括在这里的原因)但事实上这只是一个骗局

50Mb泄漏的真正原因是一个静态变量。我在launcher活动中将PApplet对象声明为静态对象(希望它具有应用程序范围)然后将它导入到我的第二个活动中,我用它来实例化一个处理草图,并使用PFragment将草图绑定到该活动。好的,在关闭第二个活动时,是这个PApplet对象(在启动程序活动中声明,在第二个活动中实例化)留在内存中并导致了问题

只需将PApplet声明移动到第二个活动,以便GC可以正确地清除它,就可以解决所有内存泄漏问题

感谢所有花时间帮忙的人


西蒙

请出示你的PF片段