【问题标题】:Android - RecyclerView NullPointerException getItemCount?Android - RecyclerView NullPointerException getItemCount?
【发布时间】:2016-08-02 07:47:27
【问题描述】:

我有一个 recyclerView,它让我崩溃:

这是我的 StartActivity :

public class StartActivity extends AppCompatActivity {

    TextView txtTest;
    private ProgressDialog pDialog;
    // These tags will be used to cancel the requests
    private String tag_json_obj = "jobj_req", tag_json_arry = "jarray_req";

    private RecyclerView.Adapter mAdapter;
    RecyclerView UserCode_Recycler;
    private LinearLayoutManager mLayoutManager;


    List<Marketing_Code> userCodeList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_start);
        txtTest = (TextView) findViewById(R.id.txtTest);
        UserCode_Recycler = (RecyclerView) findViewById(R.id.UserCode_Recycler);
        pDialog = new ProgressDialog(this);
        pDialog.setMessage("Loading...");
        pDialog.setCancelable(false);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        if (fab != null) {
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }
            });
        }

        makeJsonArryReq();

        userCodeList = new ArrayList<>();
        // create an Object for Adapter
        mAdapter = new UserCodeList_Adapter(userCodeList, StartActivity.this);
        // set the adapter object to the Recyclerview
        UserCode_Recycler.setAdapter(mAdapter);

        mAdapter.notifyDataSetChanged();


        UserCode_Recycler.setHasFixedSize(true);

        mLayoutManager = new LinearLayoutManager(this);
        // use a linear layout manager
        UserCode_Recycler.setLayoutManager(mLayoutManager);

    }

    private void showProgressDialog() {
        if (!pDialog.isShowing())
            pDialog.show();
    }

    private void hideProgressDialog() {
        if (pDialog.isShowing())
            pDialog.hide();
    }


    /**
     * Making json array request
     */
    private void makeJsonArryReq() {
        showProgressDialog();
        JsonArrayRequest req = new JsonArrayRequest(Const.Marketing_List,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d("MYData", response.toString());
                        userCodeList = MarketingCode_JSONParser.parseFeed(response.toString());
                       /* // create an Object for Adapter
                        mAdapter = new UserCodeList_Adapter(userCodeList, StartActivity.this);
                        // set the adapter object to the Recyclerview
                        Search_Recycler.setAdapter(mAdapter);
                        mAdapter.notifyDataSetChanged();
                        //txtTest.setText(response.toString());*/
                        mAdapter.notifyDataSetChanged();
                        hideProgressDialog();
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d("Custom Log Error", "Error: " + error.getMessage());
                hideProgressDialog();
            }
        });

        // Adding request to request queue
        AppController.getInstance().addToRequestQueue(req, tag_json_arry);
        // Cancelling request
        // ApplicationController.getInstance().getRequestQueue().cancelAll(tag_json_arry);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

还有我的适配器:

public class UserCodeList_Adapter extends RecyclerView.Adapter<UserCodeList_Adapter.ViewHolder> {

    private List<Marketing_Code> ucList;
    public static Activity activity;
    public UserCodeList_Adapter(List<Marketing_Code> userCodeList, Activity activity) {
        this.ucList = userCodeList;
        this.activity = activity;
    }
    @Override
    public UserCodeList_Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // create a new view
        View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.listmarketing_cardview, null);

        // create ViewHolder
        ViewHolder viewHolder = new ViewHolder(itemLayoutView);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(UserCodeList_Adapter.ViewHolder viewHolder, int position) {
        String userCode =String.valueOf(ucList.get(position).getMarketCode());
        viewHolder.txtUserID.setText(userCode);
    }

    @Override
    public int getItemCount() {
        return ucList.size();
        //return ucList == null ? 0 : ucList.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public TextView txtUserID;

        public Marketing_Code items;

        public ViewHolder(View itemLayoutView) {
            super(itemLayoutView);

            txtUserID = (TextView) itemLayoutView.findViewById(R.id.txtUserID);
            // Onclick event for the row to show the data in toast
            itemLayoutView.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                }
            });

        }

    }
}

【问题讨论】:

    标签: android android-recyclerview android-adapter


    【解决方案1】:

    你还没有初始化你的userCodeList

    看到您的代码,您的适配器基于该列表,而它尚未初始化。因此,当适配器试图了解您的列表中有多少项目时,它会抛出 NullPointerException

    userCodeList 的声明更改为如下:

    List<Marketing_Code> userCodeList = new ArrayList<>();
    

    看到您更新的问题,您似乎基于 JSON 响应的数据。如果是这种情况,那么您当前的操作几乎是正确的。

    观察你的代码的这个稍微修改的sn-p:

    private void makeJsonArryReq() {
        showProgressDialog();
        JsonArrayRequest req = new JsonArrayRequest(Const.Marketing_List,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d("MYData", response.toString());
                        /* YOUR OLD CODE -> */ // userCodeList = MarketingCode_JSONParser.parseFeed(response.toString());
                        /* HOW IT SHOULD'VE BEEN */ userCodeList.addAll(MarketingCode_JSONParser.parseFeed(response.toString()));
                        mAdapter.notifyDataSetChanged();
                        hideProgressDialog();
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d("Custom Log Error", "Error: " + error.getMessage());
                hideProgressDialog();
            }
        });
    
    // ...
    

    看上面sn-p的注释部分。这样做应该可以解决您的问题并使数据在屏幕上可见。

    【讨论】:

    • 现在不要让我崩溃,但我的列表还空着吗?
    • 这是真的吗? String userCode =String.valueOf(ucList.get(position).getMarketCode());
    • 嗯,它是.. 你应该在稍后的过程中填写List。只需拨打adapter.notifyDataSetChaged() 即可,您应该会在屏幕上看到您的项目。
    • 我应该在哪里使用 mAdapter.notifyDataSetChanged(); ?
    • 填写您的List.. 您从哪里获取数据?
    【解决方案2】:

    两种处理方式:

    1. 在请求检查列表大小之前,您需要检查列表是否为 NULL

      public int getItemCount () {
          if(ucList == null)
              return 0;
          return ucList.size();
      }
      
    2. 或者,这是解决此问题的推荐方法,是在开始时将其初始化为空列表,或确保始终在关联适配器访问它之前对其进行初始化。

      List&lt;Marketing_Code&gt; userCodeList = new ArrayList&lt;&gt;();

    希望这会有所帮助。

    【讨论】:

    • 第一种方法可能有效。但不能保证它会停止由nullList 引起的后续崩溃。适配器严重依赖他们的List,所以它一开始就不应该是null
    • 同意。更新了回答点 2,以在访问前通过初始化说明推荐的方法
    【解决方案3】:

    我认为您需要对列表使用 replaceAll 函数,而不是直接等同。 这里

     userCodeList = MarketingCode_JSONParser.parseFeed(response.toString());
    

    在初始化适配器之前尝试检查 userCodeList 是否包含任何数据。

    【讨论】:

      【解决方案4】:

      请执行以下操作并尝试

         // create an Object for Adapter        
          userCodeList = new ArrayList<>();
          mAdapter = new UserCodeList_Adapter(userCodeList, StartActivity.this);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-12
        • 2021-05-13
        • 2020-02-11
        • 2021-11-20
        • 2016-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多