首页 > 解决方案 > Android:尝试在 onBindViewHolder 中的空对象引用上调用虚拟方法

问题描述

我的应用程序应该解析 JSON 数据并将其显示在回收站视图中。当我运行该应用程序时,它崩溃并出现以下错误:在此处输入图像描述

我已经多次重新检查我的代码以确保我调用了正确的资源文件,但我仍然找不到问题的根源。logcat 告诉我问题出在回收器视图适配器类中的 onBindViewHolder 方法中,但对我来说一切正常。谁能指出我正确的方向?以下是相关代码:

回收站视图适配器:

    public class IndRvAdapter extends RecyclerView.Adapter<IndRvAdapter.MyViewHolder> {

    private Context context;
    private List<Ind> indList;

    public IndRvAdapter(Context context, List<Ind> indList) {
        this.context = context;
        this.indList = indList;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view;
        LayoutInflater inflater = LayoutInflater.from(context);
        view = inflater.inflate(R.layout.ind_card, viewGroup, false);
        final MyViewHolder viewHolder = new MyViewHolder(view);
        viewHolder.indView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent i = new Intent(context, SingleInd.class);
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                i.putExtra("pacshort", indList.get(viewHolder.getAdapterPosition()).getPacshort());
                i.putExtra("supopp", indList.get(viewHolder.getAdapterPosition()).getSuppopp());
                i.putExtra("candname", indList.get(viewHolder.getAdapterPosition()).getCandname());
                i.putExtra("district", indList.get(viewHolder.getAdapterPosition()).getDistrict());
                i.putExtra("amount", indList.get(viewHolder.getAdapterPosition()).getAmount());
                i.putExtra("party", indList.get(viewHolder.getAdapterPosition()).getExpParty());
                i.putExtra("payee", indList.get(viewHolder.getAdapterPosition()).getPayee());
                i.putExtra("date", indList.get(viewHolder.getAdapterPosition()).getDate());
                i.putExtra("origin", indList.get(viewHolder.getAdapterPosition()).getOrigin());
                i.putExtra("source", indList.get(viewHolder.getAdapterPosition()).getSource());
                context.startActivity(i);
            }
        });
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int i) {
        myViewHolder.pacshorts.setText(indList.get(i).getPacshort());
        myViewHolder.supOpp.setText(indList.get(i).getSuppopp());
        myViewHolder.candName.setText(indList.get(i).getCandname());
        myViewHolder.district.setText(indList.get(i).getDistrict());
    }

    @Override
    public int getItemCount() {
        return indList.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder{
        TextView pacshorts, supOpp, candName, district;
        LinearLayout indView;
        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            pacshorts = itemView.findViewById(R.id.tv_pacshort);
            supOpp = itemView.findViewById(R.id.tv_suppopp);
            candName = itemView.findViewById(R.id.tv_candname);
            district = itemView.findViewById(R.id.tv_district);
            indView = itemView.findViewById(R.id.ind_view);
        }
    }
}

卡片查看资源:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:id="@+id/ind_view">

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:layout_gravity="center"
        android:layout_margin="5dp"
        android:elevation="3dp"
        card_view:cardCornerRadius="15dp"
        card_view:cardElevation="4dp"
        card_view:cardUseCompatPadding="true">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/colorPrimaryDark">

            <TextView
                android:id="@+id/pacshort"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:text="TextView" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/pacshort"
                android:id="@+id/tv_suppop"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/tv_candname"
                android:layout_below="@+id/tv_suppop"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/tv_district"
                android:layout_below="@+id/tv_candname"/>
        </RelativeLayout>
    </android.support.v7.widget.CardView>


</LinearLayout>

回收商视图:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/background_color"
    tools:context=".IndExpend">

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/ind_rv">
    </android.support.v7.widget.RecyclerView>

</RelativeLayout>

解析 JSON 数据的主要活动

    public class IndExpend extends AppCompatActivity {
    /*
    * Open secrets API: Returns the 50 latest independent expenditures transactions
    * Updated every 4 days
    */

    private static final String url = "http://www.opensecrets.org/api/?method=independentExpend&output=json&apikey=d1ff8f708ca0745d75e9ffa0ee6f3d09";
    private LinearLayoutManager linearLayoutManager;
    private List <Ind> indList;
    private RecyclerView myrv;
    private RecyclerView.Adapter adapter;

    public IndExpend(){}

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ind_expend);

        linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);

        myrv = findViewById(R.id.ind_rv);
        indList = new ArrayList<>();
        adapter = new IndRvAdapter(this, indList);

        myrv.setHasFixedSize(true);
        myrv.setLayoutManager(linearLayoutManager);
        myrv.setAdapter(adapter);

        getData();
    }

    private void getData() {
        final ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Loading...");
        progressDialog.show();

        StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                progressDialog.dismiss();
                try {
                    JSONObject object = new JSONObject (response);
                    JSONObject responseObj = object.getJSONObject("response");
                    JSONArray array = responseObj.getJSONArray("indexp");
                    for (int i = 0; i < array.length(); i++){
                        JSONObject attributesObj = array.getJSONObject(i).getJSONObject("@attributes");
                        Ind ind = new Ind(attributesObj.getString("pacshort"),
                                attributesObj.getString("suppopp"),
                                attributesObj.getString("candname"),
                                attributesObj.getString("district"),
                                attributesObj.getString("amount"),
                                attributesObj.getString("party"),
                                attributesObj.getString("payee"),
                                attributesObj.getString("date"),
                                attributesObj.getString("origin"),
                                attributesObj.getString("source"));
                        indList.add(ind);
                    }
                    adapter = new IndRvAdapter(getApplicationContext(), indList);
                    myrv.setAdapter(adapter);
                }catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("Volley", error.toString());
                progressDialog.dismiss();
            }
        });
        RequestQueue requestQueue = Volley.newRequestQueue(this );
        requestQueue.add(stringRequest);
    }
}

谁能帮我找到问题的根源?

标签: android-recyclerviewandroid-cardview

解决方案


我认为这是因为您试图将视图与此 ID 绑定:

pacshorts = itemView.findViewById(R.id.tv_pacshort);

但在布局文件中,该元素的 id 只是 pacshort:

<TextView
            android:id="@+id/pacshort"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="TextView" />

通常,在 Android 上工作时,这些类型的空指针异常发生的原因有两个。首先,正在膨胀的 res 文件不是正确的,或者,其次,用于绑定视图的 id 拼写错误或在该视图中不存在。


推荐阅读