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

内存耗尽后ListView触发NullPointerException问题求助

问题分析与解决方案

这个问题我之前也碰到过,本质是系统内存回收后Activity重建时,生命周期回调顺序变化导致的:

正常启动应用时,你的Activity会先执行setContentView,完成a_images、a_emotes这些ListView实例的初始化,之后才会附加Fragment并触发onSectionAttached方法,所以一切正常。但当系统因内存不足回收你的Activity后,再次重建时,系统会先恢复Fragment的状态,触发Fragment的onAttach回调(进而调用你的onSectionAttached),而此时你的Activity可能还没完成setContentView和ListView的初始化,导致a_images还是null,调用它的方法就会抛出NullPointerException。

解决方案

1. 立即生效:添加Null检查(防御性编程)

这是最快修复崩溃的方式,在调用ListView的任何方法前,先判断它是否为null:

public void onSectionAttached(int number) {
    switch (number) {
        case 1:
            status = 1;
            mTitle = getString(R.string.title_section1);
            // 先检查ListView是否已初始化完成
            if (a_images != null) {
                a_images.invalidateViews();
                a_images.refreshDrawableState();
            }
            break;
        // 处理其他case逻辑...
    }
}

2. 更优雅:延迟操作到视图完全初始化后

你可以把ListView的刷新逻辑延迟到Activity视图完全初始化之后,比如在onPostCreate方法中处理(onPostCreate会在onCreate和所有视图初始化完成后调用):

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    // 根据保存的状态执行对应的ListView刷新
    if (status == 1 && a_images != null) {
        a_images.invalidateViews();
        a_images.refreshDrawableState();
    }
}

同时修改onSectionAttached,只保存状态不直接操作ListView:

public void onSectionAttached(int number) {
    switch (number) {
        case 1:
            status = 1;
            mTitle = getString(R.string.title_section1);
            break;
        // 其他case逻辑...
    }
}

3. 最佳实践:让Fragment管理自己的视图(如果适用)

如果你的ListView是Fragment布局的一部分,建议把ListView的初始化和操作逻辑移到Fragment内部,这样Fragment可以自己控制视图生命周期,避免跨组件的空指针问题:

public class PlaceholderFragment extends Fragment {
    private ListView a_images;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.your_fragment_layout, container, false);
        // 在Fragment内部初始化ListView
        a_images = rootView.findViewById(R.id.ascii_images);
        // 初始化适配器等逻辑
        return rootView;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        // 仅通知Activity更新标题,ListView操作留在Fragment内部
        ((MainActivity) context).onSectionAttached(1);
    }

    // 在Fragment的合适生命周期中刷新ListView
    @Override
    public void onResume() {
        super.onResume();
        if (a_images != null) {
            a_images.invalidateViews();
            a_images.refreshDrawableState();
        }
    }
}

额外提示

别忘了在Activity中保存关键状态,内存回收后重建时可以恢复之前的状态:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("status", status);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // 初始化ListView
    a_images = (ListView) findViewById(R.id.ascii_images);
    a_emotes = (ListView) findViewById(R.id.ascii_emotes);
    // 恢复之前保存的状态
    if (savedInstanceState != null) {
        status = savedInstanceState.getInt("status");
    }
}

内容的提问来源于stack exchange,提问作者Jonáš Tichý

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:31:43