使用activity活动两个片段之间的通信会产生NullPointerException

时间:2018-02-22 10:30:28

标签: android android-fragments nullpointerexception android-volley

我有一个活动,只要点击cpt_loader按钮就会加载片段bookingscpt_loader显示循环进度条,直到使用MySQL databaseVolley library获取数据。收到响应后,cpt_loader会立即使用接口将JSONObject发送到MainActivity。它完美地工作到这一点,数据也在MainActivity中收到。但是,当我使用接口再次从MainActivitybookings片段发送JSONObject时,我得到:

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

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);
    }
}

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);
    }
}

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();
        }
    }

}

此外,在此link的官方Android文档中,数据从片段传递到活动,但与我的应用程序相反,活动直接处理第二个片段中的视图。我不知道一个活动是否能够使用接口向片段发送数据。

2 个答案:

答案 0 :(得分:1)

这不会这样。这是2个问题:

  1. 您没有在MainActivity中初始化sendListener
  2. 如果您从sendListener片段初始化bookings,它可能无法一直有效。因为无法保证bookings会在您致电MainActivity之前初始化并附加到mListener.sendCPT(response);。如果在调用bookings之前未创建并附加mListener.sendCPT(response);片段,则您的sendListener将为空。创建sendListener Fragment并附加到Activity后,bookings将有效。
  3. 你可以用其他方式做到。您可以将JSONObject保存在MainActivity中。当bookings片段附加到MainActivity时,您只需从getMeJson()片段调用MainActivity方法bookings即可。并检查是否为空或有效。

    <强> MainActivity

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

    预订片段

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

答案 1 :(得分:0)

我发现使用setter或其他函数而不是接口发送数据TO Fragments更容易。

Fragment targetFragment = GetFragmentManager.findFragmentByTag("targetFragment ");
if(targetFragment != null){
  ((MyFragmentClass) targetFragment).receiveData(data);
}