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

Android中每60秒执行代码崩溃问题解决求助

解决Android Fragment中定时任务更新UI的CalledFromWrongThreadException问题

问题原因分析

从你的错误日志和代码来看,核心问题是后台线程直接操作UI:

  • 你在onCreateView里虽然用了getActivity().runOnUiThread(),但紧接着又启动了一个新的后台线程,这个线程每隔60秒调用getData()方法。
  • getData()方法的第一行mainExplore_progressBar.setVisibility(View.VISIBLE)是在后台线程中执行的,而Android明确规定:只有创建视图层次结构的主线程才能操作视图,因此触发了CalledFromWrongThreadException。

修复方案

我们需要做到三点:

  1. 定时任务的调度逻辑可以在后台线程,但调用getData()的操作必须切换到主线程。
  2. 使用更可靠的定时任务工具(ScheduledExecutorService)替代手动线程+sleep的方式,避免线程阻塞和不稳定问题。
  3. 在Fragment销毁时停止定时任务,防止内存泄漏。

修改后的完整代码片段

首先添加定时任务服务的成员变量:

public class MainReminderFragment extends Fragment {
    // ... 其他已有成员变量
    private ScheduledExecutorService scheduler; // 新增定时任务服务

    // ... 其他已有代码

然后替换onCreateView中的定时任务逻辑:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // ... 其他初始化代码(保持不变)

    // 替换原来的定时任务逻辑
    scheduler = Executors.newSingleThreadScheduledExecutor();
    // 延迟0秒启动,每隔60秒执行一次任务
    scheduler.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            if (isRunning && getActivity() != null) {
                // 切换到主线程执行getData,确保所有UI操作在主线程完成
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        getData();
                    }
                });
            }
        }
    }, 0, 60, TimeUnit.SECONDS);

    return view;
}

添加Fragment销毁时的清理逻辑,避免内存泄漏:

@Override
public void onDestroyView() {
    super.onDestroyView();
    isRunning = false;
    // 停止定时任务,释放资源
    if (scheduler != null) {
        scheduler.shutdownNow();
    }
}

另外优化Adapter的设置逻辑(只需要初始化时设置一次):
在onCreateView的RecyclerView初始化部分,提前设置好Adapter:

// RecyclerView
mainExplore_recyclerView.setLayoutManager(layoutManager);
mainExplore_recyclerView.setHasFixedSize(true);
mainExplore_recyclerView.setAdapter(reminderAdapter); // 移到此处,仅设置一次

然后在getData()的onResponse回调中,移除mainExplore_recyclerView.setAdapter(reminderAdapter);这一行,保留reminderAdapter.notifyDataSetChanged();即可。

修复逻辑说明

  • ScheduledExecutorService是Java标准库提供的定时任务工具,比手动创建线程+sleep更稳定,支持灵活的调度策略,还能避免线程阻塞问题。
  • 通过getActivity().runOnUiThread()确保getData()全程在主线程执行,所有UI操作(比如ProgressBar的可见性切换、RecyclerView数据更新)都符合Android的线程规则。
  • 在onDestroyView中停止定时任务,避免Fragment销毁后任务仍在后台运行导致的内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:24:48