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

SQLite读取仅返回最后元素,Firestore位置对比异常求助

问题分析与解决方案

你遇到的核心问题是全局变量被循环覆盖,导致仅保留SQLite数据库中最后一条收藏位置的数据。我们来拆解问题并修复它:

问题根源

在listFavoriteLocation()方法的最后,你用一个for循环把全局变量List_FAVCurrentLocationLAT和List_FAVCurrentLocationLONG反复赋值为每个收藏位置的经纬度:

for (DataModel mo:data ) {
    this.List_FAVCurrentLocationLAT = mo.getFAVCurrentLocationLAT();
    this.List_FAVCurrentLocationLONG = mo.getFAVCurrentLocationLONG();
    // ...日志输出
}

循环结束后,这两个全局变量只会保存最后一次循环的赋值结果(也就是最后一条收藏位置)。当你在readFirestore()的文档循环里调用listFavoriteLocation()时,拿到的自然永远是最后一条数据。

修复方案

我们需要直接使用listFavoriteLocation()返回的完整收藏位置列表,而不是依赖全局变量。同时优化逻辑,避免重复读取SQLite数据库:

  1. 先缓存所有收藏位置:在Firestore查询成功后,先一次性获取所有收藏位置,不要在每个文档循环里重复调用listFavoriteLocation()
  2. 遍历每个收藏位置与Firestore位置对比:对每个Firestore的活动位置,遍历所有收藏位置计算距离,符合条件就写入数据库

修改后的readFirestore()代码如下:

public void readFirestore() {
    FirebaseFirestore db = FirebaseFirestore.getInstance();
    // 先获取所有收藏位置,缓存起来
    List<DataModel> favoriteLocations = listFavoriteLocation();
    
    db.collection("campaigns")
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful() && task.getResult() != null) {
                        for (QueryDocumentSnapshot document : task.getResult()) {
                            String name = document.getString("name");
                            String cityLAT = document.getString("cityLAT");
                            String cityLONG = document.getString("cityLONG");
                            String campaignStartDate = document.getString("campaignStartDate");
                            String campaignEndDate = document.getString("campaignEndDate");

                            // 遍历所有收藏位置,逐个对比距离
                            for (DataModel favLoc : favoriteLocations) {
                                String favLatStr = favLoc.getFAVCurrentLocationLAT();
                                String favLongStr = favLoc.getFAVCurrentLocationLONG();
                                
                                try {
                                    double favLat = Double.parseDouble(favLatStr);
                                    double favLong = Double.parseDouble(favLongStr);
                                    double campaignLat = Double.parseDouble(cityLAT);
                                    double campaignLong = Double.parseDouble(cityLONG);

                                    // 计算距离(保留你的原有计算逻辑)
                                    double theta = campaignLong - favLong;
                                    double dist = Math.sin(Math.toRadians(favLat)) * Math.sin(Math.toRadians(campaignLat)) 
                                                + Math.cos(Math.toRadians(favLat)) * Math.cos(Math.toRadians(campaignLat)) * Math.cos(Math.toRadians(theta));
                                    dist = Math.acos(dist);
                                    dist = Math.toDegrees(dist);
                                    dist = dist * 60 * 1.1515;
                                    dist = dist * 1.609344;

                                    if (dist <= 0.5) { // 500米以内
                                        // 建议使用参数化SQL防止注入
                                        ContentValues values = new ContentValues();
                                        values.put("FAVCampaignName", name);
                                        values.put("FAVCampaigncampaignStartDate", campaignStartDate);
                                        values.put("FAVCampaigncampaignEndDate", campaignEndDate);
                                        // 使用replace代替execSQL更安全
                                        SQLITEDATABASEFavCampaign.replace("myTable3", null, values);
                                        
                                        Log.i("helloname","符合条件的活动:"+name);
                                    }
                                } catch (NumberFormatException e) {
                                    // 处理字符串转数字失败的情况
                                    Log.e("LocationError", "经纬度格式错误:" + e.getMessage());
                                }
                            }
                        }
                        Toast.makeText(CampaignActivity.this,"完成位置匹配", Toast.LENGTH_SHORT).show();
                    } else {
                        Log.e("FirestoreError", "读取数据失败:" + task.getException());
                        Toast.makeText(CampaignActivity.this,"读取数据失败", Toast.LENGTH_SHORT).show();
                    }
                }
            });
}

同时,你可以移除listFavoriteLocation()里的全局变量赋值循环,因为已经不需要了:

public List<DataModel> listFavoriteLocation(){
    db = new DatabaseHelper(this);
    SQLiteDatabase mydb = db.getWritableDatabase();
    List<DataModel> data=new ArrayList<>();
    Cursor csr = mydb.rawQuery("select * from "+TABLE+" ;",null);
    
    DataModel dataModel = null;
    while (csr.moveToNext()) {
        dataModel= new DataModel();
        String FAVCurrentLocationLAT = csr.getString(csr.getColumnIndexOrThrow("FAVCurrentLocationLAT"));
        String FAVCurrentLocationLONG = csr.getString(csr.getColumnIndexOrThrow("FAVCurrentLocationLONG"));
        dataModel.setFAVCurrentLocationLAT(FAVCurrentLocationLAT);
        dataModel.setFAVCurrentLocationLONG(FAVCurrentLocationLONG);
        data.add(dataModel);
    }
    csr.close(); // 记得关闭Cursor,避免资源泄漏
    mydb.close(); // 关闭数据库连接
    
    // 移除这个全局变量赋值的循环
    /*for (DataModel mo:data ) {
        this.List_FAVCurrentLocationLAT = mo.getFAVCurrentLocationLAT();
        this.List_FAVCurrentLocationLONG = mo.getFAVCurrentLocationLONG();
        Log.i("helloLAT",""+List_FAVCurrentLocationLAT);
        Log.i("helloLONG",""+List_FAVCurrentLocationLONG);
    }*/
    
    return data;
}

额外优化建议

  • 关闭Cursor和数据库连接:在listFavoriteLocation()里记得关闭Cursor和SQLiteDatabase,避免资源泄漏
  • 参数化SQL语句:使用ContentValues和replace()方法代替直接拼接SQL字符串,防止SQL注入攻击
  • 异常处理:添加NumberFormatException的捕获,处理经纬度字符串格式错误的情况
  • Toast时机调整:把Toast放在Firestore回调内部,确保操作完成后再提示用户

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:32:15