GLTextureView复用

目录

结论

分析

参考

结论

答案:无法复用

如果想知道为什么就继续,不想就可以关闭了。

分析

以下会借鉴多篇文章

textureView的两种使用场景 - 简书 

从这里可以看到,surfaceTexture会被销毁掉,我便按照以上的方式尝试了一下。

但运行后出现报错:

Cannot setSurfaceTexture to a released SurfaceTexture

便找了

不能setSurfaceTexture到释放表面纹理 - VoidCC 

 直接覆写 onSurfaceTextureDestoryed()方法,返回 false。

发现结果还是不可以。

这时我便看了源码 setSurfaceTexture 方法

    /**
     * Set the {@link SurfaceTexture} for this view to use. If a {@link
     * SurfaceTexture} is already being used by this view, it is immediately
     * released and not usable any more.  The {@link
     * SurfaceTextureListener#onSurfaceTextureDestroyed} callback is <b>not</b>
     * called for the previous {@link SurfaceTexture}.  Similarly, the {@link
     * SurfaceTextureListener#onSurfaceTextureAvailable} callback is <b>not</b>
     * called for the {@link SurfaceTexture} passed to setSurfaceTexture.
     *
     * The {@link SurfaceTexture} object must be detached from all OpenGL ES
     * contexts prior to calling this method.
     *
     * @param surfaceTexture The {@link SurfaceTexture} that the view should use.
     * @see SurfaceTexture#detachFromGLContext()
     */
    public void setSurfaceTexture(@NonNull SurfaceTexture surfaceTexture) {
        if (surfaceTexture == null) {
            throw new NullPointerException("surfaceTexture must not be null");
        }
        if (surfaceTexture == mSurface) {
            throw new IllegalArgumentException("Trying to setSurfaceTexture to " +
                    "the same SurfaceTexture that's already set.");
        }
        if (surfaceTexture.isReleased()) {
            throw new IllegalArgumentException("Cannot setSurfaceTexture to a " +
                    "released SurfaceTexture");
        }
        if (mSurface != null) {
            nDestroyNativeWindow();
            mSurface.release();
        }
        mSurface = surfaceTexture;
        nCreateNativeWindow(mSurface);

        /*
         * If the view is visible and we already made a layer, update the
         * listener in the new surface to use the existing listener in the view.
         * Otherwise this will be called when the view becomes visible or the
         * layer is created
         */
        if (((mViewFlags & VISIBILITY_MASK) == VISIBLE) && mLayer != null) {
            mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
        }
        mUpdateSurface = true;
        invalidateParentIfNeeded();
    }

抛异常是根据 surfaceTexture.isReleased() 来判断的,

继续追溯

    /**
     * {@code release()} frees all the buffers and puts the SurfaceTexture into the
     * 'abandoned' state. Once put in this state the SurfaceTexture can never
     * leave it. When in the 'abandoned' state, all methods of the
     * {@code IGraphicBufferProducer} interface will fail with the {@code NO_INIT}
     * error.
     * <p>
     * Note that while calling this method causes all the buffers to be freed
     * from the perspective of the the SurfaceTexture, if there are additional
     * references on the buffers (e.g. if a buffer is referenced by a client or
     * by OpenGL ES as a texture) then those buffer will remain allocated.
     * <p>
     * Always call this method when you are done with SurfaceTexture. Failing
     * to do so may delay resource deallocation for a significant amount of
     * time.
     *
     * @see #isReleased()
     */
    public void release() {
        nativeRelease();
    }

    /**
     * Returns {@code true} if the SurfaceTexture was released.
     *
     * @see #release()
     */
    public boolean isReleased() {
        return nativeIsReleased();
    }
isReleased() 会返回 nativeIsReleased() ; 是通过native层实现的。

发现 release() 也是同样调用。

便查看 release() 在何处调用

private void releaseSurfaceTexture() {
        if (mSurface != null) {
            boolean shouldRelease = true;

            if (mListener != null) {
                shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface);
            }

            synchronized (mNativeWindowLock) {
                nDestroyNativeWindow();
            }

            if (shouldRelease) {
                mSurface.release();
            }
            mSurface = null;
            mHadSurface = true;
        }
    }

发现是根据变量 shouldRelease 来判断,而 shouldRelease 又是根据  onSurfaceTextureDestroyed() 返回值。

这和我上边覆写onSurfaceTextureDestroyed() 返回 false是同样的,

说明 shouldRelease == false 也是会导致GLTextureView无法复用。

继续追溯 releaseSurfaceTexture() 会在哪里调用?

    /** @hide */
    @Override
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    protected void onDetachedFromWindowInternal() {
        destroyHardwareLayer();
        releaseSurfaceTexture();
        super.onDetachedFromWindowInternal();
    }

 你会发现是在 onDetachedFromWindowInternal()被调用,而这个是只有在你窗口被移除的时候才会调用。

所以,只要你把view不显示,就会调用 releaseSurfaceTexture(),onDetachedFromWindowInternal() 还注解 @UnsupportedAppUsage,所以对无法其进行覆写。

结论:GLTextureView无法复用。

参考

textureView的两种使用场景 

不能setSurfaceTexture到释放表面纹理 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值