简体   繁体   中英

NullPointerExceptions when parsing Json using Gson on Android

I'm a bit new to posting on StackOverflow. I've done a whole bunch of searching, and I can't seem to find an answer that helps me solve my specific problem.

I am trying to parse this particular Json: https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=fuzzy%20monkey%27

I'm new to Json, and I am using Google Gson in order to parse it. It compiles fine. However it doesn't seem as if my Java classes are being populated with the proper info from the Json (I keep getting NullPointerExceptions), which is probably due to my lack of knowledge about Json. In this code, the NullPointerException comes specifically from the final int N = response.results.size() line from my Main Activity.

My Main Activity:

public class MainActivity extends ActionBarActivity {

    public static InputStream json;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment()).commit();
        }

        ResponseData response = new ResponseData();

        new JsonAsync(this, response).execute();

        final int N = response.results.size();
        final TextView[] myTextViews = new TextView[N]; // create an empty array;

        for (int i = 0; i < N; i++) {
            // create a new textview
            final TextView textView = new TextView(this);

            textView.setText("Image Name:" + response.results.get(i).titleNoFormatting);


            RelativeLayout myLayout = (RelativeLayout) findViewById(R.id.container);
            // add the textview to the linearlayout
            myLayout.addView(textView);

            // save a reference to the textview for later
            myTextViews[i] = textView;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container,
                    false);
            return rootView;
        }
    }

    /**
     * Async Task for Grabbing Json Data
     *
     */
    private static class JsonAsync extends AsyncTask<Void, Void, ResponseData> {

        private String text;
        public InputStream stream;
        private Activity activity;
        private ResponseData response;

        public JsonAsync(Activity activity, ResponseData response) {
            this.activity = activity;
            this.response = response;
        }

        @Override
        protected ResponseData doInBackground(Void...params) {
            try {
                URL url = new URL("https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=fuzzy%20monkey%27");
                InputStream stream = url.openStream();

                Gson gson = new Gson();
                String json = convertStreamToString(stream);

                ResponseData response = gson.fromJson(json, ResponseData.class);
                return response;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;

        }

        @Override
        protected void onPostExecute(ResponseData result) {
            super.onPostExecute(result);
        }

        public static String convertStreamToString(java.io.InputStream is) {
            java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
            return s.hasNext() ? s.next() : "";
        }
    }

}

My Result Class:

public class Result {

    public int width;
    public int height;
    public String visibleUrl;
    public String titleNoFormatting;
    public URL url;

    public Result () {

    }
}

My ResponseData class:

public class ResponseData {
     public List<Result> results;
}

I was starting off very basic, just taking a few values from the Json to put into the class and trying to display just the names of the image searches in dynamically created TextViews (based on the search count). I have network permissions already declared in the manifest so I don't think it's a network problem. Any help would be appreciated!

You should put all your code that depends on asynctask in onPostExecute.

@Override
protected void onPostExecute(ResponseData result) {
    final int N = result.results.size();
    final TextView[] myTextViews = new TextView[N]; // create an empty array;

    for (int i = 0; i < N; i++) {
        // create a new textview
        final TextView textView = new TextView(MainActivity.this);

        textView.setText("Image Name:" + result.results.get(i).titleNoFormatting);


        RelativeLayout myLayout = (RelativeLayout) findViewById(R.id.container);
        // add the textview to the linearlayout
        myLayout.addView(textView);

        // save a reference to the textview for later
        myTextViews[i] = textView;
    }

    super.onPostExecute(result);
}

EDIT: I missed a thing. Wherever was response.results use result.results instead. It was in two lines:

final int N = result.results.size();

and

textView.setText("Image Name:" + result.results.get(i).titleNoFormatting);

If you get null again, maybe it is because name of your class 'ResponseData' and mark in json 'responseData' are not the same (first letter).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM