Android 移动SurfaceView时从JNI绘制到曲面
在我的应用程序中,我的活动布局中有一个Android 移动SurfaceView时从JNI绘制到曲面,android,android-ndk,surfaceview,Android,Android Ndk,Surfaceview,在我的应用程序中,我的活动布局中有一个SurfaceView,因此它的表面不受任何片段生命周期的影响。我使用以下代码从JNI绘制曲面(一些变量是全局的): 只要我不改变SurfaceView的大小和位置,这就非常有效。但是,当我开始绘图时,调整SurfaceView的大小和位置(内容调整得很好),停止绘图,然后再次启动,我得到以下错误: E/BufferQueue:[SurfaceView]连接:已连接(cur=2,req=2) 到目前为止,我的SurfaceView是消费者,而ANativeW
SurfaceView
,因此它的表面不受任何片段生命周期的影响。我使用以下代码从JNI绘制曲面(一些变量是全局的):
只要我不改变SurfaceView
的大小和位置,这就非常有效。但是,当我开始绘图时,调整SurfaceView
的大小和位置(内容调整得很好),停止绘图,然后再次启动,我得到以下错误:
E/BufferQueue:[SurfaceView]连接:已连接(cur=2,req=2)
到目前为止,我的SurfaceView
是消费者,而ANativeWindow
是生产者。SurfaceView拥有一个缓冲队列
,它将显示数据(由memcpy复制)从生产者发送到消费者端。因此,在更改大小和位置后,其中一个(我不确定是哪个)正在尝试再次连接到该缓冲队列。因为在我的代码中,我没有调用队列/获取
等。具体来说,我不确定如何防止这种情况
我不知道的是:是从NDK侧的ANativeWindow\u lock
调用连接还是从surface调用连接?锁方法接收到的缓冲区是否会泄漏以防止下次连接?我还向锁定和解锁结果中添加了日志消息,发现在更改大小和位置后,ANativeWindow\u lock
失败。这对我来说似乎很奇怪,因为我的解锁只在锁定成功时执行,而我根本没有从Java端锁定曲面。如果我尝试解锁它,那么从JNI我会得到:
Surface::unlockAndPost失败,没有锁定的缓冲区
我还考虑了其他内存泄漏,并用LeakCanary进行了分析。这不会发现任何泄漏,即使我手动执行堆转储,但我不确定它在本机代码中的效果如何
如果我不画,这个错误就不会出现。你对此有什么想法吗
如果重要的话,我正在Android KitKat(4.4.2)上开发。非常感谢您的帮助。调整曲面大小由SurfaceFlinger完成,您无法在调整/移动过程中绘制。您必须检测窗口何时移动/调整大小,并停止尝试锁定它以进行绘图。我在两个片段之间切换时调整SurfaceView的大小。所以你的意思是,我应该在事务期间锁定表面,并在事务结束时释放它?
lockCanvas
和unlockCanvasAndPost
是正确的方法吗?当您要更改像素时,可以使用锁定/解锁:在当前处理同一曲面时,从do changes中预先设置其他(其他线程)。您必须释放所有锁(lockCanvas()的数量应与unlock()的数量相同),并等待直到曲面可以自由锁定或可用。如果我记得很清楚,有一种方法可以在尝试锁定画布之前检查SurfaceView的可用性。当SurfaceView由SurfaceFlinger(或其他人)持有时,您必须停止在其上绘制。然后您必须确保调用unlockCanvas()的时间与锁定方法的时间相同。感谢您的解释,我明天会尝试!但是为什么它第一次工作(只要我不停止画画,内容移动和缩放都很好)tho?
void onDraw() {
int height=0, width=0;
ANativeWindow_Buffer nativeBuffer;
ARect redrawRect;
if (nativeWindow != NULL) {
height = ANativeWindow_getHeight(nativeWindow);
width = ANativeWindow_getWidth(nativeWindow);
redrawRect.left = 0;
redrawRect.top = 0;
redrawRect.right = width;
redrawRect.bottom = height;
if (ANativeWindow_lock(nativeWindow, &nativeBuffer, &redrawRect) == 0) {
height = (redrawRect.bottom - redrawRect.top);
width = (redrawRect.right - redrawRect.left);
bufferSize= height * width * 4;
memcpy(nativeBuffer.bits, pbuf, bufferSize);
ANativeWindow_unlockAndPost(nativeWindow);
}
}
}