商丘网站建设流程,分类网站一天做几条合适,深圳租房,网页设计页面图片谨慎使用android.view.SurfaceView.setVisibility方法
why?
原因就是此方法会导致native的内存暴增#xff0c;前提条件你使用surfaceview去绘制一些复杂的3D图形#xff0c;绘制复杂、业务复杂的场景#xff1b; setVisibility方法会调用surfaceView的updateSurface,而此…谨慎使用android.view.SurfaceView.setVisibility方法
why?
原因就是此方法会导致native的内存暴增前提条件你使用surfaceview去绘制一些复杂的3D图形绘制复杂、业务复杂的场景 setVisibility方法会调用surfaceView的updateSurface,而此方法内部就可能会分配大量的native内存
分析
查看 updateSurface源码 /** hide */
protected void updateSurface() {final boolean formatChanged mFormat ! mRequestedFormat;final boolean visibleChanged mVisible ! mRequestedVisible;final boolean creating (mSurfaceControl null || formatChanged || visibleChanged) mRequestedVisible;.....if (creating) {viewRoot.createBoundsSurface(mSubLayer);mSurfaceSession new SurfaceSession();mDeferredDestroySurfaceControl mSurfaceControl;updateOpaqueFlag();final String name SurfaceView - viewRoot.getTitle().toString();mSurfaceControl new SurfaceControl.Builder(mSurfaceSession).setName(name).setOpaque((mSurfaceFlags SurfaceControl.OPAQUE) ! 0).setBufferSize(mSurfaceWidth, mSurfaceHeight).setFormat(mFormat).setParent(viewRoot.getSurfaceControl()).setFlags(mSurfaceFlags).build();mBackgroundControl new SurfaceControl.Builder(mSurfaceSession).setName(Background for - name).setOpaque(true).setColorLayer().setParent(mSurfaceControl).build();} else if (mSurfaceControl null) {return;}.....
}如上函数重点在于满足creating为true的情况下new SurfaceControl.Builder在这个builder里面会直接创建SurfaceControl对象在SurfaceControl构造方法中有一个
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,SurfaceControl parent, SparseIntArray metadata){mNativeObject nativeCreate(session, name, w, h, format, flags,parent ! null ? parent.mNativeObject : 0, metaParcel);
}nativeCreate是一个native方法在native层的代码如下
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject,jobject metadataParcel) {....SurfaceControl *parent reinterpret_castSurfaceControl*(parentObject);spSurfaceControl surface;......status_t err client-createSurfaceChecked(String8(name.c_str()), w, h, format, surface, flags, parent, std::move(metadata));.....return reinterpret_castjlong(surface.get());
}status_t SurfaceComposerClient::createSurfaceChecked(const String8 name, uint32_t w, uint32_t h,PixelFormat format,spSurfaceControl* outSurface, uint32_t flags,SurfaceControl* parent,LayerMetadata metadata) {spSurfaceControl sur;status_t err mStatus;if (mStatus NO_ERROR) {spIBinder handle;spIBinder parentHandle;spIGraphicBufferProducer gbp;if (parent ! nullptr) {parentHandle parent-getHandle();}err mClient-createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),handle, gbp);.....}return err;
}到这里就不继续往下分析不过也不难看出就是要重新创建一个surface上面的createSurfaceChecked方法中的“IGraphicBufferProducer”代码就是分配对应的图像内存的例证所以从上surfaceView的setVisibility方法很有可能就在native层分配内存如果频繁调用setVisibility方法而又没做好回收工作就极有可能使内存暴增系统和应用奔溃出现android.view.Surface$OutOfResourcesException异常
如果频繁setVisiviblity方法分配内存系统会将当前surface对象之前分配的内存回收掉吗
看了SurfaceView的updateSurface函数里面有将之前创建的SurfaceControl回收掉但是回收掉有一些列条件比较复杂我也没去深入的研究有兴趣的可以自行去分析
总结在项目中如果没有存在内存泄露而内存暴增又来源于native可以参考是否来源于surfaceview当然native也不仅限于此还有其他的共享内存、自己代码的业务内存等要多方面综合考虑