Search code examples
javaandroidandroid-asynctaskandroid-arrayadapterandroid-sharedpreferences

Android plotting markers null pointer on postExecute


How do I fix a java.lang.NullPointerException on my for loop. I am guessing I am not getting a value at list_location.size() and Also, a NPE on sharePreferences onBackground. What I'm trying to do is to plot all markers on postExecute and store it's data on sharedpreferences while its running onBackground.

Question, how do I get the value of list_location that was added here list_location.add(new LocationHolder(lat, lng, location, remarks)); on my onBackground and get it at onPostExecute?

public class SnailTrailFragment extends Fragment implements OnMapReadyCallback {

private ProgressDialog pDialog;

ArrayList<LocationHolder> list_location;

public static GoogleMap mMapSnailTrail;

public static String baseUrl = "http://mark.journeytech.com.ph/mobile_api/";
public static NetworkAPI networkAPI;

Context context;
static Activity activity;

public SnailTrailFragment(Context c, Activity a) {
    context = c;
    activity = a;
}

public interface NetworkAPI {
    @POST("snailtrail.php")
    @Headers({"Content-Type:application/json; charset=UTF-8"})
    Call<JsonElement> loginRequest(@Body SnailTrailPojo body);
}

public static class SnailTrailPojo {
    String platenum;
    String datetimefrom;
    String datetimeto;
    String client_table;

    public SnailTrailPojo(String platenum, String datetimefrom, String datetimeto, String client_table) {
        this.platenum = platenum;
        this.datetimefrom = datetimefrom;
        this.datetimeto = datetimeto;
        this.client_table = client_table;
    }
}

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

    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.fragment_contact_us, container, false);

    return v;
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map1);
    mapFragment.getMapAsync(this);

}

@Override
public void onMapReady(GoogleMap googleMap) {
    mMapSnailTrail = googleMap;
    new GetSnailTrail().execute();
    mMapSnailTrail.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(12.405888, 123.273419), 6));
}

class GetSnailTrail extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // Showing progress dialog
        pDialog = new ProgressDialog(getActivity());
        pDialog.setMessage("Please wait...");
        pDialog.setCancelable(false);
        pDialog.show();
    }

    @Override
    protected Void doInBackground(Void... arg0) {

        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();

        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

        httpClient.addInterceptor(logging);
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .client(httpClient.build())
                .build();

        networkAPI = retrofit.create(NetworkAPI.class);

        SnailTrailPojo loginRequest = new SnailTrailPojo(vm.getPlate_num(), /*"08/03/2017 00:00:00"*/ BottomSheetModalFragment.dateFrom, "08/04/2017 23:59:59", client_table);

        System.out.println(vm.getPlate_num() + client_table + BottomSheetModalFragment.dateFrom + " asdas");

        Call<JsonElement> call = networkAPI.loginRequest(loginRequest);

        call.enqueue(new Callback<JsonElement>() {
            @Override
            public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
                // success response
                if (response.body().isJsonArray()) {
                    JsonArray objectWhichYouNeed = response.body().getAsJsonArray();
   //                    System.out.println(response.body() + " "+ "Response");

                    list_location = new ArrayList<>();
                    for (int i = 0; i < response.body().getAsJsonArray().size(); i++) {

                        JsonElement location_array = response.body().getAsJsonArray().get(i);
                        JsonObject location_obj = location_array.getAsJsonObject();
                        String location = location_obj.get("location").toString();

                        JsonElement lat_array = response.body().getAsJsonArray().get(i);
                        JsonObject lat_obj = lat_array.getAsJsonObject();
                        String lati = lat_obj.get("lat").toString();
                        String latiString = lati;
                        latiString = latiString.replace("\"", "");
                        String lat = String.valueOf(latiString);

                        JsonElement lng_array = response.body().getAsJsonArray().get(i);
                        JsonObject lng_obj = lng_array.getAsJsonObject();
                        String longi = lng_obj.get("lng").toString();
                        String longiString = longi;
                        longiString = longiString.replace("\"", "");
                        String lng = String.valueOf(longiString);

                        JsonElement remarks_array = response.body().getAsJsonArray().get(i);
                        JsonObject remarks_obj = remarks_array.getAsJsonObject();
                        String remarks = remarks_obj.get("remarks").toString();
                        if (lat != null && !lat.equals("null") && (lng != null && !lng.equals("null"))) {
                            list_location.add(new LocationHolder(lat, lng, location, remarks));
                        }



                        SharedPreferences preferences = context.getSharedPreferences("AppPrefs", MODE_PRIVATE);
                        SharedPreferences.Editor prefsEditor = preferences.edit();

                        Gson gson = new Gson();

                        String jsonText = gson.toJson(list_location);
                        prefsEditor.putString("key", jsonText);
                        prefsEditor.commit();
                    }

                } else {
                    System.out.println("Not a JSONArray.");
                }
            }

            @Override
            public void onFailure(Call<JsonElement> call, Throwable t) {
                // failure response
                System.out.println("Fail " + call.toString());
            }

        });

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        // Dismiss the progress dialog
        if (pDialog.isShowing())
            pDialog.dismiss();

final PolylineOptions polylineOptions = new PolylineOptions();
                            for (int j = 0; j < list_location.size(); j++) {

                                // Setting the color of the polyline
                                polylineOptions.color(Color.RED);

                                // Setting the width of the polyline
                                polylineOptions.width(3);

                                Double d1 = Double.parseDouble(list_location.get(j).getLatitude());
                                Double d2 = Double.parseDouble(list_location.get(j).getLongitude());

                                Toast.makeText(getContext(), d1 + d2.toString(),Toast.LENGTH_LONG).show();
                                // Setting points of polyline
                                polylineOptions.add(new LatLng(d1, d2));

                                createMarker(j, d1, d2, list_location.get(j).getRemarks());

                            }
                            // Adding the polyline to the map
                            mMapSnailTrail.addPolyline(polylineOptions);

/*            Gson gson = new Gson();
        SharedPreferences myPrefs;
        myPrefs = context.getSharedPreferences("AppPrefs", MODE_PRIVATE);
        String jsonText = myPrefs.getString("key", null);

        Type collectionType = new TypeToken<List<LocationHolder>>(){}.getType();
        List<LocationHolder> addArray= (List<LocationHolder>) new Gson()
                .fromJson( jsonText , collectionType);*/

    }
}

public void createMarker(int index, Double latitude, Double longitude, String snippet) {
    // Adding the taped point to the ArrayList
    BitmapDescriptor image = BitmapDescriptorFactory.fromResource(R.drawable.bus);

    mMapSnailTrail.addMarker(new MarkerOptions()
            .position(new LatLng(latitude, longitude))
            .anchor(0.5f, 0.5f)
            .title(snippet)
            .snippet(snippet)
            .icon(image));

    mMapSnailTrail.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude, longitude), 15.0f));

    mMapSnailTrail.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
        @Override
        public void onInfoWindowClick(Marker marker) {
            marker.hideInfoWindow();
        }
    });
}

public class MarkerInfoWindowAdapter implements GoogleMap.InfoWindowAdapter {

    public MarkerInfoWindowAdapter() {
    }

    @Override
    public View getInfoWindow(Marker marker) {
        return null;
    }

    @Override
    public View getInfoContents(final Marker marker) {
        View v = getActivity().getLayoutInflater().inflate(R.layout.marker_popup, null);
        Button b = (Button) v.findViewById(R.id.button2);
        b.setOnClickListener(new Button.OnClickListener() {

            @Override
            public void onClick(View v) {
                marker.hideInfoWindow();
            }
        });
        TextView markerLabel = (TextView) v.findViewById(R.id.textView2);
        markerLabel.setText("");

        return v;
    }
}
}

Logs

java.lang.NullPointerException
                                                   at com.journeytech.mark.mark.fragment.SnailTrailFragment$GetSnailTrail.onPostExecute(SnailTrailFragment.java:227)
                                                   at com.journeytech.mark.mark.fragment.SnailTrailFragment$GetSnailTrail.onPostExecute(SnailTrailFragment.java:122)
                                                   at android.os.AsyncTask.finish(AsyncTask.java:632)
                                                   at android.os.AsyncTask.access$600(AsyncTask.java:177)
                                                   at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
                                                   at android.os.Handler.dispatchMessage(Handler.java:102)
                                                   at android.os.Looper.loop(Looper.java:136)
                                                   at android.app.ActivityThread.main(ActivityThread.java:5021)
                                                   at java.lang.reflect.Method.invokeNative(Native Method)
                                                   at java.lang.reflect.Method.invoke(Method.java:515)
                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:827)
                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:643)

Here's the second log

java.lang.NullPointerException at com.journeytech.mark.mark.fragment.SnailTrailFragment$GetSnailTrail$1.onResponse(SnailTrailFragment.java:212) at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5021) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:827)


Solution

  • Problem:

    You are using retrofit to get reponse using enqueue which asynchronously sends the request.

    No what you are doing is calling enqueue asynchronously, and there is no need for it. Your AsyncTask finishes before you get your response in onResponseand when you make a for loop inside your postExecuteyou get null pointer becuase the list is not updated yet and you try to access it.

       @Override
    public void onMapReady(GoogleMap googleMap) {
        mMapSnailTrail = googleMap;
        // Remove asynctask since you are already using retrofit enqueue
        // new GetSnailTrail().execute();
        //Create a new method to call api using retrofit
        getDataFromServer();
        mMapSnailTrail.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(12.405888, 123.273419), 6));
    }
    
    private void getDataFromServer() {
    
        /**
        *Show Progress dialog here      
        */
    
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    
        httpClient.addInterceptor(logging);
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .client(httpClient.build())
                .build();
    
        networkAPI = retrofit.create(NetworkAPI.class);
    
        SnailTrailPojo loginRequest = new SnailTrailPojo(vm.getPlate_num(), /*"08/03/2017 00:00:00"*/ BottomSheetModalFragment.dateFrom, "08/04/2017 23:59:59", client_table);
    
        System.out.println(vm.getPlate_num() + client_table + BottomSheetModalFragment.dateFrom + " asdas");
    
        Call<JsonElement> call = networkAPI.loginRequest(loginRequest);
    
        call.enqueue(new Callback<JsonElement>() {
            @Override
            public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
                // success response
    
               /**
               * Hide the progress dialog here
               */
    
                if (response.body().isJsonArray()) {
                    JsonArray objectWhichYouNeed = response.body().getAsJsonArray();
                    //                    System.out.println(response.body() + " "+ "Response");
    
                    list_location = new ArrayList<>();
                    for (int i = 0; i < response.body().getAsJsonArray().size(); i++) {
    
                        JsonElement location_array = response.body().getAsJsonArray().get(i);
                        JsonObject location_obj = location_array.getAsJsonObject();
                        String location = location_obj.get("location").toString();
    
                        JsonElement lat_array = response.body().getAsJsonArray().get(i);
                        JsonObject lat_obj = lat_array.getAsJsonObject();
                        String lati = lat_obj.get("lat").toString();
                        String latiString = lati;
                        latiString = latiString.replace("\"", "");
                        String lat = String.valueOf(latiString);
    
                        JsonElement lng_array = response.body().getAsJsonArray().get(i);
                        JsonObject lng_obj = lng_array.getAsJsonObject();
                        String longi = lng_obj.get("lng").toString();
                        String longiString = longi;
                        longiString = longiString.replace("\"", "");
                        String lng = String.valueOf(longiString);
    
                        JsonElement remarks_array = response.body().getAsJsonArray().get(i);
                        JsonObject remarks_obj = remarks_array.getAsJsonObject();
                        String remarks = remarks_obj.get("remarks").toString();
                        if (lat != null && !lat.equals("null") && (lng != null && !lng.equals("null"))) {
                            list_location.add(new LocationHolder(lat, lng, location, remarks));
                        }
    
    
    
                        SharedPreferences preferences = context.getSharedPreferences("AppPrefs", MODE_PRIVATE);
                        SharedPreferences.Editor prefsEditor = preferences.edit();
    
                        Gson gson = new Gson();
    
                        String jsonText = gson.toJson(list_location);
                        prefsEditor.putString("key", jsonText);
                        prefsEditor.commit();
    
    
                        //Move the on postExecute code here
    
                        final PolylineOptions polylineOptions = new PolylineOptions();
                        for (int j = 0; j < list_location.size(); j++) {
    
                            // Setting the color of the polyline
                            polylineOptions.color(Color.RED);
    
                            // Setting the width of the polyline
                            polylineOptions.width(3);
    
                            Double d1 = Double.parseDouble(list_location.get(j).getLatitude());
                            Double d2 = Double.parseDouble(list_location.get(j).getLongitude());
    
                            Toast.makeText(getContext(), d1 + d2.toString(),Toast.LENGTH_LONG).show();
                            // Setting points of polyline
                            polylineOptions.add(new LatLng(d1, d2));
    
                            createMarker(j, d1, d2, list_location.get(j).getRemarks());
    
                        }
                        // Adding the polyline to the map
                        mMapSnailTrail.addPolyline(polylineOptions);
    
                    }
    
                } else {
                    System.out.println("Not a JSONArray.");
                }
            }
    
            @Override
            public void onFailure(Call<JsonElement> call, Throwable t) {
                // failure response
                System.out.println("Fail " + call.toString());
            }
    
        });
    }