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

Android RecyclerView调用setAdapter报空对象引用异常排查

问题报错

运行应用时触发空指针异常,报错信息如下:

Attempt to invoke virtual method 'void androidx.recyclerview.widget.RecyclerView.setAdapter(androidx.recyclerview.widget.RecyclerView$Adapter)' on a null object reference

项目基于BottomNavigationView实现多Fragment切换,id为mRecyclerView的RecyclerView控件定义在HomeFragment的布局文件中,在MainActivity中直接通过findViewById获取控件实例后执行初始化操作时持续触发该空指针,参考同类问题方案无法适配当前项目场景。

关联代码

MainActivity 实现代码

package com.sti.lazshop;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;

import com.sti.lazshop.databinding.ActivityMainBinding;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    ActivityMainBinding binding;
    ArrayList<ItemModel> itemModels = new ArrayList<>();
    int[] itemImages = {R.drawable.item_huion, R.drawable.item_iphone};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        RecyclerView recyclerView = findViewById(R.id.mRecyclerView);
        Item_RecyclerViewAdapter adapter = new Item_RecyclerViewAdapter(this, itemModels);
        setItemModels();
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        replaceFragment(new HomeFragment());

        binding.bottomNavigationView2.setOnItemSelectedListener(item -> {

            switch (item.getItemId()) {
                case R.id.home:
                    replaceFragment(new HomeFragment());
                    break;
                case R.id.cart:
                    replaceFragment(new CartFragment());
                    break;
                case R.id.account:
                    replaceFragment(new AccountFragment());
                    break;

            }
            return true;
        });

    }

    private void replaceFragment(Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.frameLayout, fragment);
        fragmentTransaction.commit();

    }

    private void setItemModels() {
        String[] itemNames = getResources().getStringArray(R.array.item_full_txt);
        String[] itemPrices = getResources().getStringArray(R.array.item_prices);

        for (int i = 0; i < itemNames.length; i++) {
            itemModels.add(new ItemModel(
                    itemNames[i],
                    itemPrices[i],
                    itemImages[i]));
        }

    }

}

HomeFragment 实现代码

package com.sti.lazshop;

import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class HomeFragment extends Fragment {

    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    private String mParam1;
    private String mParam2;

    public HomeFragment() {
    }

    public static HomeFragment newInstance(String param1, String param2) {
        HomeFragment fragment = new HomeFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        return inflater.inflate(R.layout.fragment_home, container, false);
    }
}

fragment_home.xml 布局代码

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".HomeFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/mRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>
问题根因
  • 控件查找范围不匹配:mRecyclerView属于HomeFragment布局内的控件,不在MainActivity对应的activity_main布局层级中,在MainActivity中直接调用findViewById(R.id.mRecyclerView)无法匹配到对应控件,返回值为null,后续调用setAdapter等方法必然触发空指针。
  • 执行时序错误:原代码中先执行控件查找逻辑,再调用replaceFragment加载HomeFragment布局,查找动作发生在Fragment视图被添加到窗口层级之前,哪怕控件id在Activity布局中存在,此时也拿不到有效实例。
  • 架构逻辑错误:Fragment内部的控件初始化逻辑应该放在Fragment自身的生命周期回调中实现,直接在宿主Activity中跨层级查找、操作Fragment的内部控件,不仅会触发空指针,后续Fragment切换、视图销毁重建时还会引发更多状态不一致的问题。
修复步骤
  1. 清理MainActivity中跨层级操作RecyclerView的冗余代码,删除以下片段:
RecyclerView recyclerView = findViewById(R.id.mRecyclerView);
Item_RecyclerViewAdapter adapter = new Item_RecyclerViewAdapter(this, itemModels);
setItemModels();
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));

商品数据、资源配置如果后续需要在多页面共享,建议通过ViewModel实现,不要直接在Activity中持有、操作Fragment的内部控件。

  1. 调整HomeFragment代码,在Fragment自身的视图生命周期内完成RecyclerView初始化,修改后的参考代码如下:
package com.sti.lazshop;

import android.os.Bundle;

import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;

public class HomeFragment extends Fragment {

    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    private String mParam1;
    private String mParam2;
    private ArrayList<ItemModel> itemModels = new ArrayList<>();
    private final int[] itemImages = {R.drawable.item_huion, R.drawable.item_iphone};

    public HomeFragment() {}

    public static HomeFragment newInstance(String param1, String param2) {
        HomeFragment fragment = new HomeFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_home, container, false);
        // 从Fragment自身的根视图中查找RecyclerView实例
        RecyclerView recyclerView = rootView.findViewById(R.id.mRecyclerView);
        // 初始化列表数据
        setItemModels();
        // 配置适配器与布局管理器
        Item_RecyclerViewAdapter adapter = new Item_RecyclerViewAdapter(requireContext(), itemModels);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
        return rootView;
    }

    private void setItemModels() {
        String[] itemNames = getResources().getStringArray(R.array.item_full_txt);
        String[] itemPrices = getResources().getStringArray(R.array.item_prices);

        for (int i = 0; i < itemNames.length; i++) {
            itemModels.add(new ItemModel(
                    itemNames[i],
                    itemPrices[i],
                    itemImages[i]));
        }
    }
}
  1. 开发注意事项
  • Fragment中查找内部控件时,必须通过onCreateView加载返回的根视图调用findViewById,不要直接使用Activity的查找方法,避免视图层级匹配错误。
  • Fragment中获取上下文对象优先使用requireContext()/requireActivity(),不要直接传入Fragment实例this,避免生命周期不匹配引发内存泄漏。
  • Activity与Fragment之间的数据通信、交互不要通过直接操作对方控件实现,优先选择ViewModel、Fragment Result API或接口回调方案,保证生命周期安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:15:29