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

Android绘制折线图从数据库取数时出现NullPointerException空指针异常

你遇到的空指针问题确实和异步逻辑处理不当有关,同时还有变量重名、成员变量未初始化的问题,具体原因和修复方案如下:

问题原因

  1. 自定义ViewBrokenLineCusVisitView中的mdata成员变量没有初始化,默认值为null。View加载完成后系统会自动触发onDraw绘制,此时你还没有调用setMdata给mdata赋值,遍历mdata.size()时直接触发空指针。
  2. Firebase数据库的get()请求是异步执行的,你在Spinner选中事件中发起请求,请求返回之前View已经完成了首次绘制,你加的synchronized锁无法阻止异步请求返回前onDraw的执行逻辑。
  3. 存在变量重名问题:你在Firebase请求的OnCompleteListener中声明了局部变量BrokenLineCusVisit brokenline,和全局的自定义View实例brokenline重名,导致你调用setMdata时实际指向的是局部数据类实例,自定义View的mdata始终没有被赋值。

修复方案

  • 修复自定义View空指针风险:
    要么给mdata做初始化:
    // 把BrokenLineCusVisitView中的mdata声明改成
    private List<BrokenLineCusVisit> mdata = new ArrayList<>();
    
    要么在onDraw遍历mdata前加非空判断:
    @Override
    protected void onDraw(Canvas canvas) {
        synchronized (LockObj.INSTANCE) {
            super.onDraw(canvas);
            // 加非空判断,无数据时直接返回不绘制业务逻辑
            if (mdata == null || mdata.isEmpty()) {
                return;
            }
            // 原有绘制逻辑...
        }
    }
    
  • 修复变量重名问题:把OnCompleteListener中的局部数据实例改名,避免和全局自定义View重名:
    reference.child(UserID).child("10").child(String.valueOf(i)).child("AM").get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
        @Override
        public void onComplete(@NonNull @NotNull Task<DataSnapshot> task) {
            if (!task.isSuccessful()) {
                task.getException();
                // 改名成item,不要和全局的brokenline重名
                BrokenLineCusVisit item = new BrokenLineCusVisit(finalI + "", 0);
                mdata.add(item);
            } else {
                int num = Integer.parseInt(task.getResult().getValue().toString());
                BrokenLineCusVisit item = new BrokenLineCusVisit(finalI + "", num);
                mdata.add(item);
            }
            // 这里调用的就是全局自定义View的setMdata方法
            brokenline.setMdata(mdata);
        }
    });
    
  • 优化逻辑避免数据残留:每次Spinner选中触发请求前,先清空全局的mdata,避免多次切换选项时数据累加重复:
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        String s = parent.getItemAtPosition(position).toString();
        if (s.equals("Oct")) {
            // 先清空旧数据
            mdata.clear();
            for (int i = 15; i < 16; i++) {
                // 原有请求逻辑...
            }
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 21:36:03