You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android新手求助:如何在Fragment的onViewCreated中显示加载进度条?

解决Fragment加载TensorFlow模型时的白屏+显示进度条问题

嘿,作为过来人太懂这种加载模型时白屏的尴尬了!核心问题是TensorFlow模型加载是耗时操作,直接在主线程执行会阻塞UI导致白屏,咱们得把加载逻辑放到后台线程,同时在UI层显示进度提示。下面给你一步步实现的方案:

第一步:调整Fragment布局

先在你的Fragment布局里,把TextureView和进度条(比如Material Design的CircularProgressIndicator)放在同一个父容器(比如FrameLayout)里,默认让进度条显示、TextureView隐藏:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 你的TextureView,默认隐藏 -->
    <TextureView
        android:id="@+id/textureView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone"/>

    <!-- 加载进度条,默认显示 -->
    <com.google.android.material.progressindicator.CircularProgressIndicator
        android:id="@+id/loadingProgress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:visibility="visible"/>

</FrameLayout>

第二步:在onViewCreated里实现异步加载+进度控制

这里推荐用Kotlin的协程(Android官方推荐)来做异步操作,既简洁又安全。如果你用Java的话,后面也给你补充Executor的方案。

Kotlin 实现

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val textureView = view.findViewById<TextureView>(R.id.textureView)
    val loadingProgress = view.findViewById<CircularProgressIndicator>(R.id.loadingProgress)

    // 用viewLifecycleOwner的协程,避免Fragment销毁后内存泄漏
    viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
        try {
            // 加载你的TensorFlow模型
            val model = TensorFlowLiteModel.loadModelFile(
                requireContext().assets, "your_model.tflite"
            )

            // 加载完成后切回主线程更新UI
            withContext(Dispatchers.Main) {
                loadingProgress.visibility = View.GONE
                textureView.visibility = View.VISIBLE
                // 这里初始化TextureView的相关逻辑,比如设置SurfaceTextureListener等
                setupTextureView(textureView, model)
            }
        } catch (e: Exception) {
            // 加载失败时的处理,比如显示错误提示
            withContext(Dispatchers.Main) {
                loadingProgress.visibility = View.GONE
                Toast.makeText(requireContext(), "模型加载失败: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

// 封装TextureView的初始化逻辑
private fun setupTextureView(textureView: TextureView, model: TensorFlowLiteModel) {
    textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
        override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
            // 这里处理TextureView可用后的逻辑,比如绑定相机、运行模型推理等
        }

        override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {}
        override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean = true
        override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {}
    }
}

Java 实现

如果用Java的话,可以用ExecutorService来做后台任务,用Handler切回主线程:

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    TextureView textureView = view.findViewById(R.id.textureView);
    CircularProgressIndicator loadingProgress = view.findViewById(R.id.loadingProgress);
    Handler mainHandler = new Handler(Looper.getMainLooper());

    // 后台线程加载模型
    Executors.newSingleThreadExecutor().execute(() -> {
        try {
            // 加载TensorFlow模型
            TensorFlowLiteModel model = TensorFlowLiteModel.loadModelFile(
                    requireContext().getAssets(), "your_model.tflite"
            );

            // 主线程更新UI
            mainHandler.post(() -> {
                loadingProgress.setVisibility(View.GONE);
                textureView.setVisibility(View.VISIBLE);
                setupTextureView(textureView, model);
            });
        } catch (Exception e) {
            mainHandler.post(() -> {
                loadingProgress.setVisibility(View.GONE);
                Toast.makeText(requireContext(), "模型加载失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
            });
        }
    });
}

private void setupTextureView(TextureView textureView, TensorFlowLiteModel model) {
    textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
            // 处理TextureView可用后的逻辑
        }

        @Override
        public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {}
        @Override
        public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) { return true; }
        @Override
        public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {}
    });
}

几个关键提醒

  • 绝对不要在主线程加载模型:这是导致白屏的核心原因,耗时操作必须放到后台线程
  • 进度条样式自定义:如果觉得默认的进度条不好看,可以换成自定义的加载动画(比如Lottie动画),只要保证布局层级正确即可
  • 内存泄漏防护:用viewLifecycleOwner的协程(Kotlin)或者在Fragment销毁时停止后台任务(Java),避免内存泄漏

内容的提问来源于stack exchange,提问作者Hong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:49:44