Search code examples
androidandroid-recyclerviewandroid-volleyjsonobjectrequest

Was LayoutInflater fix for RecyclerView was correct solution?


I was using this tutorials: https://www.youtube.com/watch?v=I2eYBtLWGzc

https://mzgreen.github.io/2015/06/23/How-to-hideshow-Toolbar-when-list-is-scrolling(part3)/

At first I was getting error:

java.lang.NullPointerException: Attempt to invoke virtual method android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup, boolean)' on a null object reference 
    at pl.michalz.hideonscrollexample.adapter.parttwo.MyAdapter.onCreateViewHolder(MyAdapter.java:37)
    at pl.michalz.hideonscrollexample.adapter.parttwo.MyAdapter.onCreateViewHolder(MyAdapter.java:18)

I made changes from:

@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    Log.w("myApp", "onCreateViewHolder  ");
    View view = layoutInflater.inflate(R.layout.recycler_item, parent, false);
    return new ViewHolder(view);
}

to:

   View view = layoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);

It fixed error, but only after few times I tired to emulate App. I had really hard time making this work, so I don't know if this is correct fix or my code is not good and it can make more error later.

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

    private LayoutInflater layoutInflater;
    private ArrayList<Receptas> receptasL = new ArrayList<>();

    public MyAdapter(Context context) {
        //layoutInflater = layoutInflater.from(context);


    }

    public void setReceptasList(ArrayList<Receptas> receptasL ){
        this.receptasL = receptasL;
        notifyItemRangeChanged(0, receptasL.size());
    }

    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Log.w("myApp", "onCreateViewHolder  ");
        View view = layoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(MyAdapter.ViewHolder holder, int position) {
        Receptas receptas = receptasL.get(position);
        holder.itemTextViewPav.setText(receptas.getPav());
        holder.itemTextViewIngred_sk.setText(receptas.getIngred_sk());
    }

    @Override
    public int getItemCount() {

        return receptasL == null ? 0 : receptasL.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView itemTextViewPav, itemTextViewIngred_sk;

        public ViewHolder(View itemView) {
            super(itemView);
            itemTextViewPav = (TextView) itemView.findViewById(R.id.itemTextViewPav);
            itemTextViewIngred_sk = (TextView) itemView.findViewById(R.id.itemTextViewIngred_sk);
        }
    }
}

this is fragment class for showing RecyclerView:

public class PartThreeFragment extends Fragment {

    private final String url = "http://smkbaig.esy.es/get_info_test.php";
    //pridetas
    ArrayList<Receptas> receptasAList = new ArrayList<>();
    MyAdapter myAdapter;
    RecyclerView recyclerView;
    RequestQueue requestQueue;
    Receptas receptas;

    public static PartThreeFragment createInstance() {
        PartThreeFragment partThreeFragment = new PartThreeFragment();
        Log.w("myApp", ">>partThree)");
        return partThreeFragment;
    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.w("myApp", "partThree>>");
        View view = inflater.inflate(R.layout.fragment_part_three, container, false);
        recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        myAdapter = new MyAdapter(getActivity());
        recyclerView.setAdapter(myAdapter);
        requestQueue = Volley.newRequestQueue(this.getActivity());
        volleyJson();
        return view;
    }


    public void volleyJson() {
        JsonObjectRequest jsObjRequest = new JsonObjectRequest
                (Request.Method.GET, url, (String) null, new Response.Listener<JSONObject>() {

                    @Override
                    public void onResponse(JSONObject response) {
                        try {

                            JSONArray ja = response.getJSONArray("receptai");
                            for (int i = 0; i < ja.length(); i++) {

                                JSONObject jsonObject = ja.getJSONObject(i);
                                receptas = new Receptas();
                                receptas.setPav(jsonObject.getString("pav"));
                                //receptas.setApras(jsonObject.getString("apras"));
                                receptas.setIngred_sk(jsonObject.getString("ingred_sk"));
                                receptasAList.add(receptas);
                                Log.w("myApp", "receptasAList.add(receptas); " + receptasAList.get(0).getPav());
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        //atliekamas po getRecceptas()
                        Log.w("myApp", "myAdapter.setReceptasList(receptasAList);");
                        myAdapter.setReceptasList(receptasAList);
//                         myAdapter.notifyDataSetChanged();
                        //mTextView.setText("Response: " + response.toString());
                    }
                },
                        new Response.ErrorListener() {
                            @Override
                            public void onErrorResponse(VolleyError error) {
                                // TODO Auto-generated method stub
                            }
                        }
                );
        requestQueue.add(jsObjRequest);
    }

}

There is also main activity class but I don't think it's needed.

I don't know how else ask this question if its not correct, but I would appreciate any help very much.


Solution

  • public MyAdapter(Context context) {
        //layoutInflater = layoutInflater.from(context);
    }
    

    You're mixing up static and instance methods here, which is your problem. At this point, the field layoutInflater is null. You then attempt to dereference it and call .from() on it (which is a static method).

    This will always crash with a NullPointerException since layoutInflater is null (this line is to assign it).

    Since .from() is a static method, you should instead be using:

    // Note the capitalization -- I'm using the LayoutInflater class to 
    // reference the static method, not the layoutInflater field.
    layoutInflater = LayoutInflater.from(context);