我是Android编程的新手,所以问题仍然很基础。我正在使用一个片段内的volley库,它获取一个json对象列表,然后将其添加到列表视图中。我处理片段的onCreate方法中的所有数据密集型代码,并将json保存为字符串。然后,我将字符串放在bundle outstate中,以便在重新创建片段后获取数据。在oncreate方法中,我执行if else来检查bundle是否有任何数据。然后我相应地更新视图项。但应用程序崩溃时出现空指针异常。这是我片段的代码。
package com.itsyogesh.gottago.fragments;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.JsonArrayRequest;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.itsyogesh.gottago.R;
import com.itsyogesh.gottago.adapter.CustomListAdapter;
import com.itsyogesh.gottago.adapter.ListInScrollAdapter;
import com.itsyogesh.gottago.model.ToiletList;
import com.itsyogesh.gottago.utils.AppController;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class ToiletListFragment extends Fragment {
public static final String ARG_RESPONSE = "response";
private String JSONResponse = null;
onListFragmentSelectedListener mCallback;
private GoogleMap googleMap;
private MapView mapView;
private Location location;
private int zoom;
private String url = "http://gotttago.herokuapp.com/api/toilets/";
private ProgressDialog pDialog;
private List<ToiletList> toiletList = new ArrayList<ToiletList>();
private ListView listView;
private CustomListAdapter customAdapter;
private Bundle savedInstanceState;
public ToiletListFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
customAdapter = new CustomListAdapter(getActivity());
pDialog = new ProgressDialog(getActivity());
this.savedInstanceState = savedInstanceState;
if (savedInstanceState != null) {
JSONResponse = savedInstanceState.getString(ARG_RESPONSE);
}
if(JSONResponse == null){
MapsInitializer.initialize(getActivity());
LocationManager locationManager = (LocationManager) getActivity()
.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, true);
location = locationManager.getLastKnownLocation(provider);
url = url + "nearby/?lat=" + location.getLatitude() + "&lng=" + location.getLongitude();
Log.e("URL", url);
pDialog.setMessage("Loading...");
pDialog.show();
JsonArrayRequest toiletReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
Log.e("List fragment", response.toString());
JSONResponse = null;
JSONResponse = response.toString();
hidePDialog();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
VolleyLog.d("ListFragment", "Error: " + volleyError.getMessage());
}
}
);
AppController.getInstance().addToRequestQueue(toiletReq);
hidePDialog();
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View ListFragmentView = inflater.inflate(R.layout.fragment_list, container, false);
return ListFragmentView;
}
@Override
public void onStart() {
super.onStart();
mapView = (MapView) getView().findViewById(R.id.map);
mapView.onCreate(savedInstanceState);
listView = (ListView) getView().findViewById(R.id.list);
listView.setAdapter(customAdapter);
setupMap();
Log.e(ARG_RESPONSE, JSONResponse);
setUpElements(JSONResponse);
}
public void setupMap() {
googleMap = mapView.getMap();
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
googleMap.getUiSettings().setZoomControlsEnabled(false);
googleMap.getUiSettings().setAllGesturesEnabled(true);
googleMap.setMyLocationEnabled(true);
MapsInitializer.initialize(getActivity());
LocationManager locationManager = (LocationManager) getActivity()
.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, true);
location = locationManager.getLastKnownLocation(provider);
//Log.e("My Location", location.getLatitude() + ", " + location.getLongitude());
zoom = 12;
if (location != null) {
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(
new LatLng(location.getLatitude(), location.getLongitude()));
googleMap.moveCamera(cameraUpdate);
googleMap.animateCamera(CameraUpdateFactory.zoomTo(zoom));
url = url + "nearby/?lat=" + location.getLatitude() + "&lng=" + location.getLongitude();
}
}
public void setUpElements(String responseString) {
JSONArray response = new JSONArray();
try {
response = new JSONArray(responseString);
} catch (JSONException e) {
e.printStackTrace();
}
Log.e(ARG_RESPONSE, response.toString());
//Parsing JSON
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
ToiletList toilet = new ToiletList();
toilet.setTitle(obj.getString("name"));
toilet.setGender(obj.getString("gender"));
toilet.setRating(obj.getDouble("overall_rating"));
JSONArray loc = obj.getJSONArray("loc");
Location toilet_location = new Location(obj.getString("name"));
toilet_location.setLatitude((Double) loc.get(1));
toilet_location.setLongitude((Double) loc.get(0));
double distance = 0;
if (location != null) {
distance = Math.round(location.distanceTo(toilet_location) / 10.0);
}
toilet.setDistance(distance / 100);
toilet.setToilet_id(obj.getString("_id"));
//Add marker
addMarker(toilet_location, toilet.getTitle());
toiletList.add(toilet);
} catch (JSONException e) {
e.printStackTrace();
}
}
//notifying list adapter for data changes
customAdapter.swapToiletRecords(toiletList);
ListInScrollAdapter.getListView(listView);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> arg0, View view, int position, long id) {
mCallback.onListItemSelected(JSONResponse, position);
}
}
);
}
public void addMarker(Location location, String title) {
MarkerOptions marker = new MarkerOptions().position(
new LatLng(location.getLatitude(), location.getLongitude())).title(title);
Log.e("Added marker", location.toString());
googleMap.addMarker(marker);
}
private void hidePDialog() {
if (pDialog != null) {
pDialog.dismiss();
pDialog = null;
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallback = (onListFragmentSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement onListFragmentSelectedListener");
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Save the current json response so that we don't have to utilise volley again
if (JSONResponse != null) {
outState.putString(ARG_RESPONSE, JSONResponse);
}
}
//The container activity must implement this interface so that fragment can deliver messages
public interface onListFragmentSelectedListener {
//Called by list fragment when an item is selected
public void onListItemSelected(String response, int position);
}
}
我的第一个问关于stackoverflow的问题,所以请耐心等待。
编辑:这是logcat(只是必需的片段)。
3783-3783/com.itsyogesh.gottago E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.itsyogesh.gottago, PID: 3783
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.itsyogesh.gottago/com.itsyogesh.gottago.MainActivity}: java.lang.NullPointerException: println needs a message
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2596)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2653)
at android.app.ActivityThread.access$800(ActivityThread.java:156)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1355)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5872)
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:1069)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:885)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException: println needs a message
at android.util.Log.println_native(Native Method)
at android.util.Log.e(Log.java:232)
at com.itsyogesh.gottago.fragments.ToiletListFragment.onStart(ToiletListFragment.java:133)
at android.support.v4.app.Fragment.performStart(Fragment.java:1528)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:972)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1121)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1103)
at android.support.v4.app.FragmentManagerImpl.dispatchStart(FragmentManager.java:1906)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:588)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1239)
at android.app.Activity.performStart(Activity.java:5322)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2569)
答案 0 :(得分:0)
尝试将您的oncreate代码放在View和return之间的oncreateview上。如果这没有帮助发布nullpointer日志。
答案 1 :(得分:0)
当您尝试在println needs a message
中记录null
时,会出现onStart()
NPE:
Log.e(ARG_RESPONSE, JSONResponse);
似乎JSONResponse
似乎只在生命周期的后期初始化。如果您坚持记录它,则可以将日志arg强制为非空字符串,例如通过附加一个空字符串:
Log.e(ARG_RESPONSE, "" + JSONResponse);
答案 2 :(得分:0)
Log.e(ARG_RESPONSE,JSONResponse); JSONResponse为null,我认为你应该替换你的JSON检索代码,如果不在oncreate或onstart取决于你,也可以在onResume上读取它也可能有帮助。调试它的最佳方法是避免声明空值。最好将其声明为JSONParser响应;或类似的东西和Log.e(ARG_RESPONSE,JSONResponse.toString());