0

I have the following code that makes a webcall and displays a list of data. The list displays correctly using RecyclerView, however i cannot get an onclick working from touching a row.

I have logged out the position from the onclick and that works fine but the app crashes with a NPE because the onClick variable has not been instantiated.

I know i need to do this with

mAdapter.setOnClick(this);

.

but i'm not sure where to put it.

link

How can i set the onclick within my fragment. the above post is using an Activity whereas i'm using a fragment.

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.List;

/**
 * Created by MatthewW on 01/11/2017.
 */

public class LoneworkerGetRotaActivityFragment extends Fragment {

    private static final String TAG = LoneworkerGetRotaActivityFragment.class.getSimpleName();
    AppObj appObj;
    List<Visit> mVisitList;
    String URL;
    String companyID;
    String ID2;
    String userID;

    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;






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

        appObj = (AppObj)getActivity().getApplication();
        URL = appObj.dbModel.getCompanyUrl();
        Log.e(TAG, "URL = " + URL);
        companyID = appObj.dbModel.getCompanyID();
        ID2 = appObj.dbModel.getCompanyWebServiceGuid();
        userID = appObj.dbModel.getUserID();



    }//end of onCreate






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


        LayoutInflater lf = getActivity().getLayoutInflater();
        View view = lf.inflate(R.layout.l_w_get_rota_activity_fragment, container, false);

        mRecyclerView = (RecyclerView) view.findViewById(R.id.get_rota_recycler_view);



        sendRequest();

        return view;


    }




    private void sendRequest(){



        StringRequest stringRequest = new StringRequest(URL + "/roadrunner.asmx/RRGetRota?ID1=" + companyID + "&ID2=" + ID2 + "&CarerID=" + userID + "&RotaDate=" + "2-Nov-2017",
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        //success - parse rota

                        DomParser dp = new DomParser(getActivity());
                        mVisitList = dp.parseUserRota(response);
                        Log.e(TAG, "mVisitList has size of " + mVisitList.size());

                        // use this setting to improve performance if you know that changes
                        // in content do not change the layout size of the RecyclerView
                        mRecyclerView.setHasFixedSize(true);

                        // use a linear layout manager
                        mLayoutManager = new LinearLayoutManager(getActivity());
                        mRecyclerView.setLayoutManager(mLayoutManager);

                        // specify an adapter (see also next example)
                        mAdapter = new MyAdapter(mVisitList);
                        mRecyclerView.setAdapter(mAdapter);








                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_LONG).show();
                    }
                });


        RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
        requestQueue.add(stringRequest);
    }




    public interface OnItemClicked {
        void onItemClick(int position);
    }

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


        //declare interface
        OnItemClicked onClick;



        public class ViewHolder extends RecyclerView.ViewHolder {

            public TextView tvStartDate;
            public TextView tvEndDate;
            public TextView tvDuration;
            public TextView tvClientForeName;
            public TextView tvClientSurName;


            public ViewHolder(View v) {
                super(v);
                tvStartDate = (TextView) v.findViewById(R.id.get_rota_startdate);
                tvEndDate = (TextView) v.findViewById(R.id.get_rota_enddate);
                tvDuration = (TextView) v.findViewById(R.id.get_rota_duration);
                tvClientForeName = (TextView) v.findViewById(R.id.get_rota_forename);
                tvClientSurName = (TextView) v.findViewById(R.id.get_rota_surname);
            }




        }//end of viewholder





        // Provide a suitable constructor (depends on the kind of dataset)
        public MyAdapter(List<Visit> myVisitList) {
            mVisitList = myVisitList;
        }

        // Create new views (invoked by the layout manager)
        @Override
        public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.get_rota_row_layout, parent, false);

            return new ViewHolder(v);
        }

        // Replace the contents of a view (invoked by the layout manager)
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            // - get element from your dataset at this position
            // - replace the contents of the view with that element

            final int pos = position;

            DateTimeFormatter fmt = DateTimeFormat.forPattern("H:mm");


            String strStartDate = mVisitList.get(position).getStartDate();
            DateTime dtStartTime = new DateTime(strStartDate);
            String formattedStartTime = fmt.print(dtStartTime);
            holder.tvStartDate.setText(formattedStartTime);

            String strEndDate = mVisitList.get(position).getEndDate();
            DateTime dtEndTime = new DateTime(strEndDate);
            String formattedEndTime = fmt.print(dtEndTime);
            holder.tvEndDate.setText(formattedEndTime);

            holder.tvDuration.setText(mVisitList.get(position).getDuration());
            holder.tvClientForeName.setText(mVisitList.get(position).getClientForename());
            holder.tvClientSurName.setText(mVisitList.get(position).getClientSurname());




            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.e(TAG, "onclick pos = " + pos);
                    onClick.onItemClick(pos);

                }
            });



        }

        // Return the size of your dataset (invoked by the layout manager)
        @Override
        public int getItemCount() {
            return mVisitList.size();
        }


        public void setOnClick(OnItemClicked onClick)
        {
            this.onClick=onClick;
        }

    }//end of adapter class









}//end of class

.

 11-07 15:53:01.268 2701-2701/loneworker.carefreegroup.com.loneworker E/LoneworkerGetRotaActivityFragment: onclick pos = 1
11-07 15:53:01.269 2701-2701/loneworker.carefreegroup.com.loneworker D/AndroidRuntime: Shutting down VM


                                                                                       --------- beginning of crash
11-07 15:53:01.273 2701-2701/loneworker.carefreegroup.com.loneworker E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                       Process: loneworker.carefreegroup.com.loneworker, PID: 2701
                                                                                       java.lang.NullPointerException: Attempt to invoke interface method 'void loneworker.carefreegroup.com.loneworker.LoneworkerGetRotaActivityFragment$OnItemClicked.onItemClick(int)' on a null object reference
                                                                                           at loneworker.carefreegroup.com.loneworker.LoneworkerGetRotaActivityFragment$MyAdapter$1.onClick(LoneworkerGetRotaActivityFragment.java:230)
                                                                                           at android.view.View.performClick(View.java:6213)
                                                                                           at android.view.View$PerformClick.run(View.java:23645)
                                                                                           at android.os.Handler.handleCallback(Handler.java:751)
                                                                                           at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                           at android.os.Looper.loop(Looper.java:154)
                                                                                           at android.app.ActivityThread.main(ActivityThread.java:6692)
                                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
                                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
turtleboy
  • 8,210
  • 27
  • 100
  • 199

2 Answers2

2

Set OnItemClicked Lister after the Creation of MyAdater Object like below

// specify an adapter (see also next example)
 mAdapter = new MyAdapter(mVisitList); // after this line

 mAdapter.setOnClick(new OnItemClicked() {
            @Override
            public void onItemClick(int position) {

            }
        });
Munir
  • 2,548
  • 1
  • 11
  • 20
  • setOnClick method exists on MyAdapter or not ? – Munir Nov 07 '17 at 16:55
  • ok then i just call that method and pass the interface which you have create in fragment. – Munir Nov 07 '17 at 17:02
  • Hi Munir, yes i have the method in the adapter and pas the inteface but the IDE is saying the method is never used?? It is like it doesn't exist, the compiler cannot see it even though it is declared in the adapter class – turtleboy Nov 08 '17 at 09:17
0

I decided to do it a different way using RecyclerTouchListener.

mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(),
                                mRecyclerView, new ClickListener() {

                            @Override
                            public void onClick(View view, final int position) {

                                Log.e(TAG, "Short press on position :" + position);

                                TextView  tvDuration = (TextView) view.findViewById(R.id.get_rota_duration);
                                String strDuration = tvDuration.getText().toString();

                                try{

                                    Integer.parseInt(strDuration);

                                    //TODO create a visit from the data from webcall (in appObj) for info passed to email, text etc

                                    Intent i = new Intent(getActivity(), LoneworkerActivity3.class);
                                    i.putExtra("duration", strDuration);
                                    startActivity(i);

                                }catch (Exception e){
                                    Toast.makeText(getActivity(), "The LoneWorker duration is not valid", Toast.LENGTH_LONG).show();
                                }





                            }

                            @Override
                            public void onLongClick(View view, int position) {

                                Log.e(TAG, "Long press on position :" + position);
                            }

                        }));

.

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






        public class ViewHolder extends RecyclerView.ViewHolder {

            public TextView tvStartDate;
            public TextView tvEndDate;
            public TextView tvDuration;
            public TextView tvClientForeName;
            public TextView tvClientSurName;


            public ViewHolder(View v) {
                super(v);
                tvStartDate = (TextView) v.findViewById(R.id.get_rota_startdate);
                tvEndDate = (TextView) v.findViewById(R.id.get_rota_enddate);
                tvDuration = (TextView) v.findViewById(R.id.get_rota_duration);
                tvClientForeName = (TextView) v.findViewById(R.id.get_rota_forename);
                tvClientSurName = (TextView) v.findViewById(R.id.get_rota_surname);
            }




        }//end of viewholder





        // Provide a suitable constructor (depends on the kind of dataset)
        public MyAdapter(List<Visit> myVisitList) {
            mVisitList = myVisitList;
        }

        // Create new views (invoked by the layout manager)
        @Override
        public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.get_rota_row_layout, parent, false);

            return new ViewHolder(v);
        }

        // Replace the contents of a view (invoked by the layout manager)
        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            // - get element from your dataset at this position
            // - replace the contents of the view with that element

            final int pos = position;

            DateTimeFormatter fmt = DateTimeFormat.forPattern("H:mm");


            String strStartDate = mVisitList.get(position).getStartDate();
            DateTime dtStartTime = new DateTime(strStartDate);
            String formattedStartTime = fmt.print(dtStartTime);
            holder.tvStartDate.setText(formattedStartTime);

            String strEndDate = mVisitList.get(position).getEndDate();
            DateTime dtEndTime = new DateTime(strEndDate);
            String formattedEndTime = fmt.print(dtEndTime);
            holder.tvEndDate.setText(formattedEndTime);

            holder.tvDuration.setText(mVisitList.get(position).getDuration());
            holder.tvClientForeName.setText(mVisitList.get(position).getClientForename());
            holder.tvClientSurName.setText(mVisitList.get(position).getClientSurname());








        }

        // Return the size of your dataset (invoked by the layout manager)
        @Override
        public int getItemCount() {
            return mVisitList.size();
        }



    }//end of adapter class

    public interface ClickListener{
        public void onClick(View view,int position);
        public void onLongClick(View view,int position);
    }


    class RecyclerTouchListener implements RecyclerView.OnItemTouchListener{

        private ClickListener clicklistener;
        private GestureDetector gestureDetector;

        public RecyclerTouchListener(Context context, final RecyclerView recycleView, final ClickListener clicklistener){

            this.clicklistener=clicklistener;
            gestureDetector=new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    return true;
                }

                @Override
                public void onLongPress(MotionEvent e) {
                    View child=recycleView.findChildViewUnder(e.getX(),e.getY());
                    if(child!=null && clicklistener!=null){
                        clicklistener.onLongClick(child,recycleView.getChildAdapterPosition(child));
                    }
                }
            });
        }

        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            View child=rv.findChildViewUnder(e.getX(),e.getY());
            if(child!=null && clicklistener!=null && gestureDetector.onTouchEvent(e)){
                clicklistener.onClick(child,rv.getChildAdapterPosition(child));
            }

            return false;
        }

        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {

        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

        }
    }
turtleboy
  • 8,210
  • 27
  • 100
  • 199