1

I have an activity which loads a fragment cpt_loader as soon as the bookings button is clicked. cpt_loader shows a circular progress bar until the data is fetched from a MySQL database using Volley library. As soon as the response is received, cpt_loader sends JSONObject to MainActivity using an interface. It works perfectly until this point and the data is also received in MainActivity. But, when I send the JSONObject again from MainActivity to bookings fragment using interface, I get:

java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.user.temporary.MainActivity$sendCPTToBookings.sendToBookings(org.json.JSONObject)' on a null object reference

Code in MainActivity.java:

package com.example.user.temporary;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class MainActivity extends AppCompatActivity implements
        cpt_loader.sendCPTToMainActivity {
    sendCPTToBookings sendListener;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        LinearLayout profilebtn = (LinearLayout)this.findViewById(R.id.profile_button);
        LinearLayout bookingsbtn = (LinearLayout)this.findViewById(R.id.bookings_button);
        LinearLayout gamesbtn = (LinearLayout)this.findViewById(R.id.games_button);
        bookingsbtn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                cpt_loader loader_frame = new cpt_loader();
                FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
                trans.replace(R.id.fragment_frame, loader_frame);
                trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                trans.commit();
            }
        });
    }

    @Override
    public void sendCPT(JSONObject cpt_json){
        sendListener.sendToBookings(cpt_json);

    }

    public interface sendCPTToBookings {
        void sendToBookings(JSONObject cpt_json);
    }
}

Code in cpt_loader.java:

package com.example.user.temporary;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;

public class cpt_loader extends Fragment {
    RequestQueue requestQueue;
    final String dataUrl = "http://10.0.2.2/futsal/main.php";
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";
    private String mParam1;
    private String mParam2;
    private sendCPTToMainActivity mListener;

    public cpt_loader() {
        // Required empty public constructor
    }

    public static cpt_loader newInstance(String param1, String param2) {
        cpt_loader fragment = new cpt_loader();
        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) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_cpt_loader, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        final ArrayList<String> cities_array = new ArrayList<String>();
        super.onViewCreated(view, savedInstanceState);
        final RelativeLayout ld = (RelativeLayout)getView().findViewById(R.id.loader);
        final RelativeLayout fb = (RelativeLayout)getView().findViewById(R.id.form_body);
        final Spinner city_sp = (Spinner)getView().findViewById(R.id.city_sp);
        requestQueue = Volley.newRequestQueue(getActivity().getApplicationContext());
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, dataUrl, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                try{
                    bookings bookings_frame = new bookings();
                    FragmentTransaction trans = getActivity().getSupportFragmentManager().beginTransaction();
                    trans.replace(R.id.fragment_frame, bookings_frame);
                    trans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                    trans.commit();
                    mListener.sendCPT(response);
                } catch (JSONException e){
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                error.printStackTrace();
            }
        });
        requestQueue.add(jsonObjectRequest);
    }

    public void onButtonPressed(JSONObject json) {
        if (mListener != null) {
            mListener.sendCPT(json);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof sendCPTToMainActivity) {
            mListener = (sendCPTToMainActivity) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }

    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface sendCPTToMainActivity {
        void sendCPT(JSONObject cpt_json);
    }
}

Code in bookings.java:

package com.example.user.temporary;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.volley.RequestQueue;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


public class bookings extends Fragment implements MainActivity.sendCPTToBookings{
    private long L1;
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    private String mParam1;
    private String mParam2;
    public bookings() {
        // Required empty public constructor
    }

    public static bookings newInstance(String param1, String param2) {
        bookings fragment = new bookings();
        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 v = inflater.inflate(R.layout.fragment_bookings, container, false);
        return v;

    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
    }

    @Override
    public void onDetach() {
        super.onDetach();

    }

    public void sendToBookings(JSONObject json_obj){
        try{
            JSONArray cities = json_obj.getJSONArray("city");
            int num_cities = cities.length();
            for(int i=0;i<num_cities;i++) {
                System.out.println(cities.getString(i));
            }
        } catch (JSONException e){
            e.printStackTrace();
        }
    }

}

Also, in the official android documentation in this link, the data is passed from fragment to the activity, but in contrary to my application, the activity directly processes the views in the second fragment. I don't know if an activity is capable of sending data to the fragment using interfaces.

2 Answers2

1

This will not work this way. Here is 2 problem:

  1. You didn't initialize sendListener in MainActivity
  2. If you initialize sendListener from bookings Fragment it may not work all time. Because there is no guarantee that bookings will be initialized and attached to MainActivity before your call mListener.sendCPT(response);. And if bookings Fragment is not created and attached before calling mListener.sendCPT(response);, your sendListener will be null. sendListener will be valid after bookings Fragment created and attached to Activity.

You can do it other way. You can save the JSONObject in MainActivity. And when bookings Fragment is attached to MainActivity you can just call a MainActivity method getMeJson() From bookings Fragment. And check if is null or valid.

MainActivity

JSONObject  jsonObject;

@Override
public void sendCPT(JSONObject cpt_json){
    jsonObject = cpt_json;
}
public JSONObject getMeJson(){
  return jsonObject;
}

bookings Fragment

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof MainActivity) {
        MainActivity activity = (MainActivity)context;
        JSONObject jsonObject = activity.getMeJson():
    }

}
Abu Yousuf
  • 5,729
  • 3
  • 31
  • 50
0

I've found that sending data TO Fragments is easier with a setter or other function than an interface.

Fragment targetFragment = GetFragmentManager.findFragmentByTag("targetFragment ");
if(targetFragment != null){
  ((MyFragmentClass) targetFragment).receiveData(data);
}
Lance Toth
  • 430
  • 3
  • 17