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

Firebase收入数据Fragment日期过滤功能异常求助

问题:Firebase收入数据Fragment日期过滤功能失效

我正尝试过滤展示从Firebase获取的收入数据的Fragment,数据展示没有问题,但过滤功能的实现却困难重重。当我尝试过滤时,日期选择器没有报错,但无法达到预期效果。

相关代码(ViewIncomeFragment.java)

过滤按钮点击事件

//Filter Button
Button filterButton = v.findViewById(R.id.btnFilter);
filterButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //Filter the Income data
        filterIncomeByDate(startDate, endDate);
        
        // Show a dialog to get start and end date from the user
        Calendar calendar2 = Calendar.getInstance();
        DatePickerDialog datePickerDialog2 = new DatePickerDialog(getContext(), new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
                if (endDate != null) {
                    endDate.setText(dayOfMonth + "-" + (month + 1) + "-" + year);
                }
                if(validateDates() == false){
                    startDate.setText("StartDate");
                    endDate.setText("EndDate");
                }
            }
            // handle the date set event
        }, calendar2.get(Calendar.YEAR), calendar2.get(Calendar.MONTH), calendar2.get(Calendar.DAY_OF_MONTH));
        datePickerDialog2.show();

        Calendar calendar1 = Calendar.getInstance();
        DatePickerDialog datePickerDialog1 = new DatePickerDialog(getContext(), new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
                if (startDate != null) {
                    startDate.setText(dayOfMonth + "-" + (month + 1) + "-" + year);
                }
            }
            // handle the date set event
        }, calendar1.get(Calendar.YEAR), calendar1.get(Calendar.MONTH), calendar1.get(Calendar.DAY_OF_MONTH));
        datePickerDialog1.show();
    }
});

return v;

日期过滤方法

//Method to filter the Income by date
public void filterIncomeByDate(TextView startDate, TextView endDate){
    ArrayList<Income> filteredList = new ArrayList<>();
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");

    try {
        Date start = dateFormat.parse(startDate.getText().toString());
        Date end = dateFormat.parse(endDate.getText().toString());
        for (Income income : incomeArrayList) {
            Date incomeDate = dateFormat.parse(income.getDateIncome());
            if (incomeDate.after(start) && incomeDate.before(end)) {
                filteredList.add(income);
            }
        }
    } catch (ParseException e) {
        e.printStackTrace();
    }
    incomeArrayList.clear();
    incomeArrayList.addAll(filteredList);
    incomeAdapter.notifyDataSetChanged();
}

预期仅展示指定日期范围内的数据,但当前无法实现该效果。


问题原因及修复方案

1. 过滤时机完全错误

点击按钮后先执行过滤,再弹出日期选择器,此时startDate、endDate还是初始占位文本(比如"StartDate"),解析会直接抛出异常,过滤逻辑根本不执行。

修复:调整流程,在用户选择完开始、结束日期后再执行过滤,并且改为顺序选择日期(先选开始,再选结束):

filterButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 先选择开始日期
        Calendar calendar1 = Calendar.getInstance();
        DatePickerDialog datePickerDialog1 = new DatePickerDialog(getContext(), new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
                if (startDate != null) {
                    startDate.setText(dayOfMonth + "-" + (month + 1) + "-" + year);
                    // 开始日期选完后,弹出结束日期选择器
                    Calendar calendar2 = Calendar.getInstance();
                    DatePickerDialog datePickerDialog2 = new DatePickerDialog(getContext(), new DatePickerDialog.OnDateSetListener() {
                        @Override
                        public void onDateSet(DatePicker view, int year2, int month2, int dayOfMonth2) {
                            if (endDate != null) {
                                endDate.setText(dayOfMonth2 + "-" + (month2 + 1) + "-" + year2);
                                // 验证日期有效后执行过滤
                                if(validateDates()){
                                    filterIncomeByDate(startDate, endDate);
                                } else {
                                    startDate.setText("StartDate");
                                    endDate.setText("EndDate");
                                }
                            }
                        }
                    }, calendar2.get(Calendar.YEAR), calendar2.get(Calendar.MONTH), calendar2.get(Calendar.DAY_OF_MONTH));
                    datePickerDialog2.show();
                }
            }
        }, calendar1.get(Calendar.YEAR), calendar1.get(Calendar.MONTH), calendar1.get(Calendar.DAY_OF_MONTH));
        datePickerDialog1.show();
    }
});

2. 原始数据源被覆盖,无法重复过滤

每次过滤都会清空incomeArrayList并替换为过滤后的数据,导致再次过滤时没有原始数据可筛选。

修复:初始化时保留一份原始数据源:

private ArrayList<Income> originalIncomeArrayList;

// 在从Firebase获取到数据后初始化
originalIncomeArrayList = new ArrayList<>(incomeArrayList);

修改过滤方法,从原始数据中筛选:

public void filterIncomeByDate(TextView startDate, TextView endDate){
    ArrayList<Income> filteredList = new ArrayList<>();
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");

    try {
        Date start = dateFormat.parse(startDate.getText().toString());
        Date end = dateFormat.parse(endDate.getText().toString());
        // 从原始数据源筛选,避免覆盖原始数据
        for (Income income : originalIncomeArrayList) {
            Date incomeDate = dateFormat.parse(income.getDateIncome());
            // 调整条件,包含开始和结束当天的数据
            if (!incomeDate.before(start) && !incomeDate.after(end)) {
                filteredList.add(income);
            }
        }
    } catch (ParseException e) {
        e.printStackTrace();
        // 解析失败时恢复原始数据展示
        filteredList = new ArrayList<>(originalIncomeArrayList);
    }
    incomeArrayList.clear();
    incomeArrayList.addAll(filteredList);
    incomeAdapter.notifyDataSetChanged();
}

3. 日期范围判断排除边界

原代码incomeDate.after(start) && incomeDate.before(end)会排除开始、结束当天的数据,改成!incomeDate.before(start) && !incomeDate.after(end)即可包含边界日期。

4. 确保日期验证逻辑有效

validateDates()方法需要严格校验开始日期不晚于结束日期,避免无效的过滤范围导致无数据展示。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:15:30