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

如何在非跳转Activity中从Model类获取数据?

解决Android跨Activity共享DataSet数据的空指针问题

首先,咱们先分析你遇到的NullPointerException大概率是哪几个原因:

  • 调用sharedPref()时传入的data是null——要么childData没初始化,要么网络请求还没跑完就急着拿数据了
  • childData里的DataSet对象本身是null
  • 你在AnnualActivity里直接用的schoolID和sessionYear变量根本没赋值,直接导致拼接URL时空指针

因为AnnualActivity不是跳转目标,没法用Intent传数据,那咱们就得用Android里跨组件共享数据的方案,下面给你几个实用的解决办法:

方案一:用自定义Application存全局数据

这是Android里最常用的全局数据共享方式,步骤很清晰:

  1. 先写一个自定义的Application子类:
public class MyApp extends Application {
    private ArrayList<DataSet> childData;

    @Override
    public void onCreate() {
        super.onCreate();
        // 提前初始化集合,避免空指针
        childData = new ArrayList<>();
    }

    public ArrayList<DataSet> getChildData() {
        return childData;
    }

    public void setChildData(ArrayList<DataSet> data) {
        this.childData.clear();
        this.childData.addAll(data);
    }
}
  1. 去AndroidManifest.xml里注册这个Application:
<application
    android:name=".MyApp"
    <!-- 你的其他配置项 -->
>
  1. 在网络请求成功的回调里,把childData存到全局Application:
    就在你第一个代码块的onResponse方法最后加这段:
// 把请求到的childData存入全局Application
MyApp myApp = (MyApp) getApplicationContext();
myApp.setChildData(childData);
  1. 最后在AnnualActivity里拿数据:
public class AnnualActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_annual);

        // 获取全局的childData
        MyApp myApp = (MyApp) getApplicationContext();
        ArrayList<DataSet> childData = myApp.getChildData();

        // 先做非空检查!这是避免空指针的关键
        if (childData != null && !childData.isEmpty()) {
            for (DataSet dataSet : childData) {
                if (dataSet == null) continue; // 跳过空的DataSet对象

                int schoolId = dataSet.getStudentSchoolId();
                String sessionYear = dataSet.getSessionYear();
                Log.e("AnnualActivity", "schoolId: " + schoolId + ", sessionYear: " + sessionYear);

                // 现在可以安全地发起你的网络请求了
                JsonObjectRequest annualReq = new JsonObjectRequest(Request.Method.GET,
                        "http://qnabubackend-env.2fuz4eh5jh.ap-south-1.elasticbeanstalk.com/school/api/annual/activity/get/list?schoolId="+schoolId+"&session="+sessionYear,
                        null,
                        response -> {
                            // 处理请求成功的逻辑
                        },
                        error -> {
                            // 处理请求失败的逻辑
                        });

                // 记得把请求加入Volley的请求队列
                Volley.newRequestQueue(this).add(annualReq);
            }
        } else {
            Log.e("AnnualActivity", "childData是空的!要么网络请求还没完成,要么请求失败了");
        }
    }
}

方案二:用SharedPreferences存关键数据

如果你只需要schoolId和sessionYear,不需要整个DataSet集合,直接存这俩值更轻便:

  1. 网络请求成功后存数据:
SharedPreferences sp = getSharedPreferences("AppData", MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();

// 这里假设你要取第一个孩子的数据,要是有多个可以遍历存成数组
if (!childData.isEmpty()) {
    DataSet firstChild = childData.get(0);
    editor.putInt("saved_school_id", firstChild.getStudentSchoolId());
    editor.putString("saved_session_year", firstChild.getSessionYear());
    editor.apply(); // 异步存,不卡主线程
}
  1. 在AnnualActivity里读数据:
SharedPreferences sp = getSharedPreferences("AppData", MODE_PRIVATE);
int schoolId = sp.getInt("saved_school_id", -1); // 默认值-1表示没取到
String sessionYear = sp.getString("saved_session_year", "");

if (schoolId != -1 && !sessionYear.isEmpty()) {
    // 放心发起网络请求
} else {
    Log.e("AnnualActivity", "没拿到schoolId或sessionYear,检查下网络请求是否成功");
}

方案三:用单例类管理共享数据

和自定义Application思路差不多,用单例类来存数据,适合不想改Application的场景:

public class DataManager {
    private static DataManager instance;
    private ArrayList<DataSet> childData;

    private DataManager() {
        childData = new ArrayList<>();
    }

    public static synchronized DataManager getInstance() {
        if (instance == null) {
            instance = new DataManager();
        }
        return instance;
    }

    public ArrayList<DataSet> getChildData() {
        return childData;
    }

    public void setChildData(ArrayList<DataSet> data) {
        this.childData.clear();
        this.childData.addAll(data);
    }
}

存数据的时候:

DataManager.getInstance().setChildData(childData);

取数据的时候:

ArrayList<DataSet> childData = DataManager.getInstance().getChildData();
// 后续的非空检查和请求逻辑和方案一一样

几个重要的注意点

  • 非空检查一定要做:不管是集合还是单个对象,访问前先判断是不是null,避免空指针
  • 注意网络请求的异步性:如果AnnualActivity比网络请求先启动,你可以用LiveData或者EventBus来监听数据变化,等数据准备好了再处理
  • 别搞内存泄漏:用全局数据的时候,别持有Activity的引用,不然容易内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:41:33