onSurfaceTextureAvailable 没有回调,通常和 TextureView 的硬件加速状态、视图可见性、监听器注册时机,以及视图是否已附加到窗口这几方面有关。下面是按排查优先级整理的原因和解决方法。
🔍 首选排查清单:检查硬件加速
这是最常见的原因,尤其容易出现在项目迁移或配置混乱时。
- 确保硬件加速已开启:
TextureView只能在硬件加速的窗口中正常工作。如果应用或 Activity 的硬件加速被关闭,TextureView将不会渲染任何内容,相关回调也不会执行。- 检查
AndroidManifest.xml中<application>或<activity>标签下是否误设置了android:hardwareAccelerated="false"。将其删除或显式设为true。 - 检查布局文件中
TextureView的android:layerType属性,不能设置为software。 - 如果上述配置都正确,可以在代码中动态确认硬件加速是否可用:
if (textureView.isHardwareAccelerated()) { // 硬件加速已启用 }
- 检查
👁️ 检查视图可见性
如果 TextureView 在设置监听器时是不可见(View.INVISIBLE 或 View.GONE)或尺寸为 0,系统可能不会为其创建 SurfaceTexture。
- 确保设置监听器时
TextureView可见且有有效尺寸。 - 如果
TextureView初始是隐藏的,请在将其可见性设置为VISIBLE之后,再注册监听器,或检查监听器是否已正确注册。
⏱️ 检查监听器注册时机
注册监听器的时机很关键。如果在 SurfaceTexture 已经准备就绪之后才设置监听器,回调将不会被触发。
- 尽早注册:建议在
onCreate()或onViewCreated()中,视图初始化完成后立即调用setSurfaceTextureListener()。如果延迟到用户点击等操作时才设置,可能已错过回调时机。 - 处理已就绪的情况:如果注册监听器时
SurfaceTexture已存在,回调不会再次触发。建议在注册后主动检查,并手动调用初始化逻辑:这个防御性检查可以覆盖很多因时序问题导致的回调丢失场景。textureView.setSurfaceTextureListener(listener); // 防止监听器设置前 SurfaceTexture 已就绪,导致回调不执行 if (textureView.isAvailable()) { listener.onSurfaceTextureAvailable( textureView.getSurfaceTexture(), textureView.getWidth(), textureView.getHeight() ); }
🌳 检查视图层级与生命周期
- 确保视图已附加到窗口:
SurfaceTexture只有在TextureView被添加到窗口(即onAttachedToWindow()被调用)之后才可用。如果TextureView没有正确添加到视图树,回调不会触发。 - 自定义 ViewGroup 的问题:将
TextureView放在自定义ViewGroup中时,如果ViewGroup的初始化或测量逻辑有问题,可能导致TextureView无法正确附加。可尝试将TextureView直接放在布局中测试,以定位问题。 - Fragment 中的问题:在 Fragment 中,确保在
onViewCreated或之后才操作视图。如果在onCreateView返回之前就尝试设置监听器,视图可能还未完全创建。
⚙️ 检查 SDK 版本配置
在项目迁移后,如果 build.gradle 和 AndroidManifest.xml 中的 SDK 版本配置不一致,也可能导致回调失败。
- 统一配置:在
build.gradle中明确指定minSdkVersion和targetSdkVersion,并移除AndroidManifest.xml中的<uses-sdk>标签,避免冲突。
🧩 其他原因与解决方案
- 多窗口/分屏模式:在多窗口模式下,窗口可能未获得焦点或处于非活跃状态,影响
SurfaceTexture的创建。可以尝试在onResume或窗口获得焦点时再检查。 - 同步模式:如果
SurfaceTexture被设置为同步模式,onFrameAvailable可能不会触发。检查是否有相关配置。 - 延迟布局请求:有时
onSurfaceTextureAvailable报告可用后,SurfaceTexture可能瞬间不可用。一个可行的解决方法是延迟一小段时间后调用requestLayout()。
🛠️ 系统性排查步骤建议
可以按以下顺序快速定位问题:
- 检查硬件加速:确认
AndroidManifest.xml和布局文件中没有禁用硬件加速。 - 检查可见性:确保设置监听器时
TextureView是VISIBLE且有非零尺寸。 - 检查注册时机:确保监听器在
onCreate/onViewCreated中尽早注册。 - 添加防御性检查:在设置监听器后,使用
if (textureView.isAvailable())手动调用回调逻辑。 - 检查视图层级:尝试将
TextureView简化到最直接的布局中测试。 - 检查 SDK 配置:确认
build.gradle和AndroidManifest.xml中的 SDK 版本配置一致。
如果以上步骤都无法解决,可以检查 Logcat 中是否有来自 TextureView 或 SurfaceTexture 的警告或错误信息,这通常会提供更直接的线索。