Android:JSON解析:尝试将JSON解析为ListView时的null对象引用

时间:2016-06-30 23:12:25

标签: android json parsing

此应用程序应该从Google Books API解析一些JSON数据(现在硬编码),并将一个BooksList of Books传递给将在ListView上显示它的适配器。我遇到的问题是JSON解析返回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) {
            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)

3 个答案:

答案 0 :(得分:0)

问题是BookAdapter adapter = new BookAdapter(this, bookList);中的一个参数由于某种原因而是null。尝试将bookList作为参数传递给updateDisplay并检查它是否不是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);
     }
}
}

答案 1 :(得分:0)

看起来你得到一个JSONParseException ...因此导致List的NullPointerExpcetion进入适配器

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
    }

这是你的错误,这是你如何得到它

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

你在这里使用那个空值

protected void updateDisplay() {

    BookAdapter adapter = new BookAdapter(this, bookList); // <-- Null here

    ListView listView = (ListView) findViewById(R.id.list);

    listView.setAdapter(adapter);
}

其次是

ArrayList<Book> bookList = new ArrayList<>();
try {
    JSONArray jsonArray = new JSONArray(content);

    // Stuff...
} catch (JSONException e) {
    e.printStackTrace();
}

return bookList;

因此,修复NullPointerExpception的方法是始终返回一个ArrayList

require 'nokogiri'

doc = Nokogiri::XML(open('1094C_Request.xml'))

doc.namespaces['xmlns'] = ''

details = doc.xpath("//:Form1095CUpstreamDetail")

elem_a = ["PersonFirstNm", "PersonLastNm", "irs:SSN"]

output = details.each_with_object({}) do |element, exp|
  exp[element.xpath("./:RecordId").text] = elem_a.each_with_object({}) do |elem_n, exp_h|
    exp_h[elem_n] = element.xpath(".//#{elem_n.include?(':') ? elem_n : ":#{elem_n}"}").text
  end
end

答案 2 :(得分:0)

从url获取json字符串你应该这样做

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

你从你提供的url得到的不是jsonArray它是一个jsonobject 所以我认为这段代码可以“假设你做的其他事情都正确”

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

你可以做for循环