Android: JSON parse: null object reference when attempting to parse JSON into a ListView

匿名 (未验证) 提交于 2019-12-03 02:44:02

问题:

This app is supposed to parse some JSON data (hard coded for now) from the Google Books API, and pass an ArrayList of Books to the adapter that will display it on a ListView. The problem I have is that the JSON parse is returning null instead of the parsed data.

public class MainActivity extends AppCompatActivity implements View.OnClickListener {      ProgressBar pBar;     List<MyTask> tasks;      ArrayList<Book> bookList;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);          pBar = (ProgressBar) findViewById(R.id.progressBar);         pBar.setVisibility(View.INVISIBLE);          Button sButton = (Button) findViewById(R.id.s_button);         sButton.setOnClickListener(this);          tasks = new ArrayList<>();      }      @Override     public void onClick(View v) {         switch (v.getId()) {             case R.id.s_button: {                 if (isOnline()) {                     new MyTask().execute("https://www.googleapis.com/books/v1/volumes?q=millionare"); //https://www.googleapis.com/books/v1/volumes?q=soft+skills                  } else {                     Toast.makeText(this, "Connection failed", Toast.LENGTH_LONG).show();                 }                 break;             }         }     }      protected boolean isOnline() {          ConnectivityManager connectManager = (ConnectivityManager)                 getSystemService(Context.CONNECTIVITY_SERVICE);          NetworkInfo netInfo = connectManager.getActiveNetworkInfo();          if (netInfo != null && netInfo.isConnectedOrConnecting()) {             return true;         } else {             return false;         }     }      private class MyTask extends AsyncTask<String, Void, String> {          @Override         protected void onPreExecute() {             super.onPreExecute();         }          @Override         protected String doInBackground(String... urls) {              // params comes from the execute() call: params[0] is the url.             try {                 return HttpManager.getData(urls[0]);             } catch (IOException e) {                 return "Unable to retrieve web page. URL may be invalid.";             }         }          @Override         protected void onPostExecute(String result) {             bookList = BookJSONParser.parseFeed(result);             updateDisplay();         }      }      protected void updateDisplay() {          BookAdapter adapter = new BookAdapter(this, bookList);          ListView listView = (ListView) findViewById(R.id.list);          listView.setAdapter(adapter);     } } 

public class BookJSONParser {       public static ArrayList<Book> parseFeed(String content) {          try {             JSONArray jsonArray = new JSONArray(content);             ArrayList<Book> bookList = new ArrayList<>();              for (int i = 0; i < jsonArray.length(); i++) {                  JSONObject object = jsonArray.getJSONObject(i);                  String name = object.getString("title").toString();                  Book book = new Book(name);                 bookList.add(book);              }              return bookList;         } catch (JSONException e) {             e.printStackTrace();             return null;         }      }  } 

public class BookAdapter extends ArrayAdapter<Book> {      public BookAdapter(Context context, ArrayList<Book> bookList) {         super(context, 0, bookList);      }      @Override     public View getView(int position, View convertedView, ViewGroup parent) {          View listItemView = convertedView;         if (listItemView == null) {             listItemView = LayoutInflater.from(getContext()).inflate(                     R.layout.list_item, parent, false);         }          Book currentBook = getItem(position);          TextView locationName = (TextView) listItemView.findViewById(R.id.book_title);          locationName.setText(currentBook.getTittle());          TextView locationAddress = (TextView) listItemView.findViewById(R.id.book_author);          locationAddress.setText(currentBook.getAuthor());          return listItemView;      } } 

public class HttpManager {      public static String getData(String myUrl) throws IOException {          // BufferedReader reader = null;          InputStream inputStream = null;          int len = 10000;          try {             URL url = new URL(myUrl);             HttpURLConnection connection = (HttpURLConnection) url.openConnection();             connection.setReadTimeout(10000 /* milliseconds */);             connection.setConnectTimeout(15000 /* milliseconds */);             connection.setRequestMethod("GET");             connection.setDoInput(true);             // Starts the query             connection.connect();             int response = connection.getResponseCode();              inputStream = connection.getInputStream();              // Convert the InputStream into a string             String contentAsString = readIt(inputStream, len);             return contentAsString;              // Makes sure that the InputStream inputStream closed after the app inputStream             // finished using it.         } finally {             if (inputStream != null) {                 try {                     inputStream.close();                 } catch (IOException e) {                     e.printStackTrace();                     return null;                 }              }         }     }   // Reads an InputStream and converts it to a String.     public static String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {         Reader reader = null;         reader = new InputStreamReader(stream, "UTF-8");         char[] buffer = new char[len];         reader.read(buffer);         return new String(buffer);     } } 

public class Book {      private String mTittle;      /**      * This is the constructor.      * @param title is the book title being passed in.      */     public Book(String title) {         mTittle = title;      }      public String getTittle() {         return mTittle;     }      public void setTittle(String tittle) {         mTittle = tittle;     }  } 

FATAL EXCEPTION: main                                                                               Process: com.narvin.android.booklisting, PID: 3278                                                                               java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference                                                                                   at android.widget.ArrayAdapter.getCount(ArrayAdapter.java:330)                                                                                   at android.widget.ListView.setAdapter(ListView.java:502)                                                                                   at com.narvin.android.booklisting.MainActivity.updateDisplay(MainActivity.java:113)                                                                                   at com.narvin.android.booklisting.MainActivity$MyTask.onPostExecute(MainActivity.java:100)                                                                                   at com.narvin.android.booklisting.MainActivity$MyTask.onPostExecute(MainActivity.java:79)                                                                                   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:145)                                                                                   at android.app.ActivityThread.main(ActivityThread.java:5942)                                                                                   at java.lang.reflect.Method.invoke(Native Method)                                                                                   at java.lang.reflect.Method.invoke(Method.java:372)                                                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)                                                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 

回答1:

The issue is that one of the arguments in BookAdapter adapter = new BookAdapter(this, bookList); is null for some reason. Try passing bookList as an argument to updateDisplay and checking whether it's not null.

public class MainActivity extends AppCompatActivity implements View.OnClickListener {  ProgressBar pBar; List<MyTask> tasks;  ArrayList<Book> bookList;  @Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);      pBar = (ProgressBar) findViewById(R.id.progressBar);     pBar.setVisibility(View.INVISIBLE);      Button sButton = (Button) findViewById(R.id.s_button);     sButton.setOnClickListener(this);      tasks = new ArrayList<>();  }  @Override public void onClick(View v) {     switch (v.getId()) {         case R.id.s_button: {             if (isOnline()) {                 new MyTask().execute("https://www.googleapis.com/books/v1/volumes?q=millionare"); //https://www.googleapis.com/books/v1/volumes?q=soft+skills              } else {                 Toast.makeText(this, "Connection failed", Toast.LENGTH_LONG).show();             }             break;         }     } }  protected boolean isOnline() {      ConnectivityManager connectManager = (ConnectivityManager)             getSystemService(Context.CONNECTIVITY_SERVICE);      NetworkInfo netInfo = connectManager.getActiveNetworkInfo();      if (netInfo != null && netInfo.isConnectedOrConnecting()) {         return true;     } else {         return false;     } }  private class MyTask extends AsyncTask<String, Void, String> {      @Override     protected void onPreExecute() {         super.onPreExecute();     }      @Override     protected String doInBackground(String... urls) {          // params comes from the execute() call: params[0] is the url.         try {             return HttpManager.getData(urls[0]);         } catch (IOException e) {             return "Unable to retrieve web page. URL may be invalid.";         }     }      @Override     protected void onPostExecute(String result) {         ArrayList<Book> bookList = BookJSONParser.parseFeed(result);         updateDisplay(bookList);     }  }  protected void updateDisplay(ArrayList<Book> bookList) {     if (bookList != null){         BookAdapter adapter = new BookAdapter(this, bookList);          ListView listView = (ListView) findViewById(R.id.list);          listView.setAdapter(adapter);      } } } 


回答2:

It would appear you are getting a JSONParseException... therefore causing a NullPointerExpcetion for the List into the Adapter

java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference 

That is your error, here is how you get it

public static ArrayList<Book> parseFeed(String content) {      try {         JSONArray jsonArray = new JSONArray(content); // <-- Throws an error         ArrayList<Book> bookList = new ArrayList<>();          // Stuff...          return bookList;     } catch (JSONException e) {         e.printStackTrace();         return null; // <----- Null is returned     } 

And you use that null value here

    @Override     protected void onPostExecute(String result) {         bookList = BookJSONParser.parseFeed(result);         updateDisplay();     } 

Followed by

protected void updateDisplay() {      BookAdapter adapter = new BookAdapter(this, bookList); // <-- Null here      ListView listView = (ListView) findViewById(R.id.list);      listView.setAdapter(adapter); } 

So, the way to fix that NullPointerExpception is to always return an ArrayList

ArrayList<Book> bookList = new ArrayList<>(); try {     JSONArray jsonArray = new JSONArray(content);      // Stuff... } catch (JSONException e) {     e.printStackTrace(); }  return bookList; 


回答3:

to get json string from url you should do it like that

String content = new MyTask()          .execute("https://www.googleapis.com/books/v1/volumes?q=millionare")          .get(); //pass the content to BookJSONParser class booklist = new BookJSONParser().parseFeed(content); updateDisplay(); 

what you get from the url you provided is NOT jsonArray it's a jsonobject so I think this code will work "assuming that you did everything else correctly"

JSONObject o = new JSONObject(content); JSONArray jsonArray = o.getJSONArray("items"); 

the you can do the for loop



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!