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

继承AsyncTask的类中For循环重复执行问题排查

问题根源与解决方案

核心问题

你的代码出现重复插入的原因有两个:

  1. onBindViewHolder被多次触发:RecyclerView的每个列表项绑定都会调用这个方法,你在里面每次都启动一个doIT异步任务,相当于多个爬取任务同时执行,每个任务都遍历链接列表(写死循环2次),导致同一条数据被多次插入。
  2. 列表元素重复添加:list.add(data.get(position))在onBindViewHolder中执行,而RecyclerView会复用ViewHolder,这个方法可能被重复调用同一个position,导致list中出现重复链接。

修复方案

应该把爬取逻辑从Adapter中剥离,Adapter只负责数据展示,爬取任务在Activity中只执行一次,遍历完整的链接列表。

1. 简化Adapter,只做展示

修改MySqliteAdapter.java,移除所有爬取相关代码:

public class MySqliteAdapter extends RecyclerView.Adapter<MySqliteAdapter.ViewHolder> {
    private final Activity activity;
    private final List<String> data;

    public MySqliteAdapter(Activity activity, List<String> data) {
        this.data = data;
        this.activity = activity;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = activity.getLayoutInflater();
        // 传入parent参数,保证布局参数生效
        View view = inflater.inflate(R.layout.custom_layout, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        // 仅负责设置文本展示,移除所有爬取逻辑
        holder.linksURL.setText(data.get(position));
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView linksURL;

        public ViewHolder(View itemView) {
            super(itemView);
            linksURL = itemView.findViewById(R.id.textView);
        }
    }
}

2. 在Activity中执行单次爬取任务

把爬取逻辑移到MainActivity,确保只启动一次任务,遍历所有链接:

public class MainActivity extends AppCompatActivity {
    private List<String> linkList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 从SQLite获取完整的链接列表
        linkList = fetchLinksFromSQLite();

        // 初始化RecyclerView
        RecyclerView recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        MySqliteAdapter adapter = new MySqliteAdapter(this, linkList);
        recyclerView.setAdapter(adapter);

        // 启动一次爬取任务
        new ScrapeTask().execute();
    }

    // 实现从SQLite获取链接的逻辑
    private List<String> fetchLinksFromSQLite() {
        List<String> links = new ArrayList<>();
        // 这里写你的SQLite查询代码,填充links列表
        return links;
    }

    private class ScrapeTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            // 遍历完整的链接列表,每个链接只爬取一次
            for (String url : linkList) {
                try {
                    Document document = Jsoup.connect(url).get();
                    Elements titleElements = document.getElementsByClass("wp-block-post-title");
                    Elements contentElements = document.getElementsByClass("has-global-padding is-layout-constrained entry-content wp-block-post-content");

                    String title = titleElements.html();
                    String content = contentElements.html();

                    insertToFirebase(title, content);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    }

    private void insertToFirebase(String title, String content) {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("title", title);
        dataMap.put("lyrics", content);

        FirebaseDatabase.getInstance().getReference()
                .child("worshipintercessor")
                .push()
                .setValue(dataMap)
                .addOnSuccessListener(unused -> {
                    // 可选:添加成功后的回调
                })
                .addOnFailureListener(e -> {
                    // 可选:失败处理
                });
    }
}

额外优化点

  • 移除了原代码中new MainActivity()的错误写法:手动创建Activity实例会导致上下文混乱,绝对禁止。
  • 布局填充时传入parent参数,保证RecyclerView的Item布局参数正常生效。
  • 原代码中doIT的循环写死为i<2,改为动态遍历完整列表,适配任意数量的链接。
  • 注意:AsyncTask在Android API 30已被废弃,建议后续改用Kotlin协程或Java ExecutorService实现异步任务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 03:05:19