首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Sceneform -如何修复泄漏的SceneView?

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

Stack Overflow用户
提问于 2022-02-11 22:57:17
回答 2查看 486关注 0票数 3

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

但现在我想找出问题的真相,并试图解决这个问题。我已经在两个版本的Sceneform上测试了它-- 1.15.0和最后一个版本,然后被Google 1.17.1否决,问题发生在这两个版本上。

泄漏发生在您使用SceneViewActivityFragment中加载模型时(我都尝试过了),然后通过执行System home navigation或通过Recent tasks list切换到不同的应用程序来“退出应用程序”。

泄漏日志:

代码语言:javascript
复制
┬───
│ 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

复制泄漏:

反对之前的最后版本:

代码语言:javascript
复制
 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

代码语言:javascript
复制
<?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 (还在片段上进行了测试)

代码语言:javascript
复制
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文件

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

若要复制,请在运行HomeRecent task list时按SceneViewSceneView按钮

我也只用SceneView测试过它,但它也会泄漏。

我该怎么解决这个漏洞?

我还在多个API、仿真器和实际设备上测试过它,所有这些都会发生这种情况。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-02-13 19:32:27

我尝试过这些方法来阻止泄漏,但他们什么也没做:

代码语言:javascript
复制
Scene scene = sceneView.getScene();
scene = null;
sceneView = null;
sceneView.destroy();
Renderer.destroyAllResources();
Renderer.reclaimReleasedResources();

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

sceneView.pause();

代码语言:javascript
复制
@Override
public void onPause()

在执行系统主页导航或通过最近的任务列表切换到另一个应用程序时,可以阻止泄漏。(执行部分中的问题)

sceneView.pause();添加到

代码语言:javascript
复制
@Override
public void onDestroy()

防止活动或碎片被破坏时发生泄漏。

代码语言:javascript
复制
    @Override
    public void onDestroy() {
        super.onDestroy();
        sceneView.pause(); 
    }
票数 2
EN

Stack Overflow用户

发布于 2022-02-13 16:43:56

正如您已经说过的,这是最后一个版本1.17.1,一些爱好者正在开发一个维护版本。也许这个版本解决了你的内存泄漏问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71087417

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档