gpt4 book ai didi

android - Sceneform - 如何修复泄漏的 SceneView?

转载 作者:行者123 更新时间:2023-12-05 03:29:06 24 4
gpt4 key购买 nike

我已经使用 SceneView 加载 3D 模型将近一年了,但我一直不明白是什么导致了这种泄漏。我会实现 LeakCanary,但只有这一次泄漏,因为我不知道如何解决这个问题。

但现在我想弄清问题的根源并尝试解决它。我已经在 Sceneform 的两个版本上对其进行了测试——1.15.0 和被 Google 1.17.1 弃用之前的最后一个版本以及两个问题都会发生。

当您在 ActivityFragment 中使用 SceneView 加载模型时会发生泄漏(我都试过了)并且您“退出”通过执行 System home navigation 或通过 Recent tasks list 切换到不同的应用程序”。

enter image description here

泄漏日志:

┬───
│ GC Root: System class

├─ android.app.ActivityThread class
│ Leaking: NO (MainActivity↓ is not leaking and a class is never leaking)
│ ↓ static ActivityThread.sCurrentActivityThread
├─ android.app.ActivityThread instance
│ Leaking: NO (MainActivity↓ is not leaking)
│ mInitialApplication instance of android.app.Application
│ ↓ ActivityThread.mActivities
├─ android.util.ArrayMap instance
│ Leaking: NO (MainActivity↓ is not leaking)
│ ↓ ArrayMap.mArray
├─ java.lang.Object[] array
│ Leaking: NO (MainActivity↓ is not leaking)
│ ↓ Object[].[1]
├─ android.app.ActivityThread$ActivityClientRecord instance
│ Leaking: NO (MainActivity↓ is not leaking)
│ activity instance of com.example.a3dmodeltester.MainActivity with
│ mDestroyed = false
│ ↓ ActivityThread$ActivityClientRecord.activity
├─ com.example.a3dmodeltester.MainActivity instance
│ Leaking: NO (SceneView↓ is not leaking and Activity#mDestroyed is false)
│ mApplication instance of android.app.Application
│ mBase instance of android.app.ContextImpl
│ ↓ MainActivity.sceneView
├─ com.google.ar.sceneform.SceneView instance
│ Leaking: NO (View attached)
│ View is part of a window view hierarchy
│ View.mAttachInfo is not null (view attached)
│ View.mID = R.id.sceneview
│ View.mWindowAttachCount = 1
│ mContext instance of com.example.a3dmodeltester.MainActivity with
│ mDestroyed = false
│ ↓ SceneView.renderer
│ ~~~~~~~~
├─ com.google.ar.sceneform.rendering.Renderer instance
│ Leaking: UNKNOWN
│ Retaining 2.9 kB in 38 objects
│ ↓ Renderer.viewAttachmentManager
│ ~~~~~~~~~~~~~~~~~~~~~
├─ com.google.ar.sceneform.rendering.ViewAttachmentManager instance
│ Leaking: UNKNOWN
│ Retaining 2.2 kB in 19 objects
│ ↓ ViewAttachmentManager.frameLayout
│ ~~~~~~~~~~~
╰→ android.widget.FrameLayout instance
​ Leaking: YES (ObjectWatcher was watching this because android.widget.
​ FrameLayout received View#onDetachedFromWindow() callback)
​ Retaining 1.9 kB in 15 objects
​ key = 10550463-895e-443a-898f-11c5131da209
​ watchDurationMillis = 5165
​ retainedDurationMillis = 157
​ View not part of a window view hierarchy
​ View.mAttachInfo is null (view detached)
​ View.mWindowAttachCount = 1
​ mContext instance of com.example.a3dmodeltester.MainActivity with
​ mDestroyed = false

METADATA

Build.VERSION.SDK_INT: 27
Build.MANUFACTURER: Google
LeakCanary version: 2.7
App process name: com.example.a3dmodeltester
Stats: LruCache[maxSize=3000,hits=892,misses=24408,hitRate=3%]
RandomAccess[bytes=1232425,reads=24408,travel=6462427001,range=8963521,size=1161
0814]
Heap dump reason: 1 retained objects, app is not visible
Analysis duration: 5411 ms

重现泄漏:

弃用前的最后一个版本:

 implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.17.1'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'

我也用 1.15.0 试过了

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.ar.sceneform.SceneView
android:id="@+id/sceneview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"/>
</RelativeLayout>

MainActivity(也测试了 fragment )

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";

private static final Vector3 STARTING_CAMERA_POSITION = new Vector3(0f, 1f, 3f);
private SceneView sceneView;
private Node node;

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

sceneView = findViewById(R.id.sceneview);
Scene scene = sceneView.getScene();
node = new Node();
scene.addChild(node);

ModelRenderable.builder()
.setSource(this, Uri.parse("Andy.sfb"))
.build()
.thenAccept(renderable -> node.setRenderable(renderable))
.exceptionally(
throwable -> {
Log.e(TAG, "Unable to load Renderable.", throwable);
return null;
});
Camera camera = scene.getCamera();
camera.setWorldPosition(STARTING_CAMERA_POSITION);
}

@Override
public void onPause() {
super.onPause();
sceneView.pause();
}

@Override
public void onResume() {
super.onResume();
try {
sceneView.resume();
} catch (CameraNotAvailableException e) {
e.printStackTrace();
}
}

@Override
public void onDestroy() {
super.onDestroy();
sceneView.destroy();
}
}

.sfb 文件

enter image description here

https://drive.google.com/file/d/1NchJ2NGNM7NZzRZkq4fewALc7m4dnGG3/view?usp=sharing

要重现,请在 SceneView 运行时按 HomeRecent task list 按钮

enter image description here

我也仅使用 SceneView 对其进行了测试,但它也会泄漏。

enter image description here

我该如何解决这个漏洞?

我还在多个 API、模拟器和真实设备上对其进行了测试,并且它发生在所有这些设备上。

最佳答案

我已经尝试了这些选项来阻止泄漏,但它们没有做任何事情:

Scene scene = sceneView.getScene();
scene = null;
sceneView = null;
sceneView.destroy();
Renderer.destroyAllResources();
Renderer.reclaimReleasedResources();

然而,这为我修复了漏洞:

中删除 sceneView.pause();
@Override
public void onPause()

在执行系统主页导航或通过“最近的任务”列表切换到其他应用程序时停止泄漏。 (OP中的问题)

添加 sceneView.pause();

@Override
public void onDestroy()

防止 Activity 或 fragment 被销毁时发生泄漏。

    @Override
public void onDestroy() {
super.onDestroy();
sceneView.pause();
}

关于android - Sceneform - 如何修复泄漏的 SceneView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71087417/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com