user7208682
user7208682

Reputation:

NullPointerException on json object

Why do I always get a NullPointerException when I run my application? Every time I start my genymotion emulator and then run the app the first time, it crashes, but the 2nd time I run my app in works smoothly. I don't know why it happens everytime on the first run.

Here is my Splash screen which retrieves the JSON object from the RetrieveGamesBGTask:

public class Splash extends Activity {
     RetrieveGamesBGTask retrieveGamesBGTask;
    String json_string;

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

        Thread thread = new Thread(){
            @Override
            public void run() {
                try {
                    retrieveGamesBGTask = new RetrieveGamesBGTask();
                    retrieveGamesBGTask.execute();
                    sleep(3000);
                    Intent intent = new Intent(getApplication(), Games.class);
                    intent.putExtra("json_data", json_string);
                    intent.putExtra("json_data", retrieveGamesBGTask.getResult());
                    startActivity(intent);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        thread.start();

Here is the next application where it crashes every time on the first run:

 retrieveGamesBGTask = new RetrieveGamesBGTask();
        retrieveGamesBGTask.execute();

  Intent intent = this.getIntent();

        if (intent != null) {
            json_string = intent.getStringExtra("json_data");
        }


        try {
            if (jsonObject == null) {
                jsonObject = new JSONObject(json_string);
                jsonArray = jsonObject.getJSONArray("server_response");
                int count = 0;
                String teamone, teamonepts, teamtwo, teamtwopts, s_name, s_gender;

                while (count < jsonArray.length()) {
                    JSONObject JO = jsonArray.getJSONObject(count);
                    teamone = JO.getString("teamone");
                    teamonepts = JO.getString("teamonepts");
                    teamtwo = JO.getString("teamtwo");
                    teamtwopts = JO.getString("teamtwopts");
                    s_name = JO.getString("s_name");
                    s_gender = JO.getString("s_gender");
                    Downloader downloader = new Downloader(teamone, teamonepts, teamtwo, teamtwopts, s_name, s_gender);
                    gamesAdapter.add(downloader);

                    count++;
                }
            } else {
                Toast.makeText(this, "JSON is null", Toast.LENGTH_LONG).show();
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

Here is my RetrieveGamesBGTask

class RetrieveGamesBGTask extends AsyncTask<Void, Void, String> {
    String json_result, json_string;

    @Override
    protected void onPreExecute() {


    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            URL url = new URL(Config.URL_GAMES);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            InputStream inputstream = httpURLConnection.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputstream));
            StringBuilder stringBuilder = new StringBuilder();
            while ((json_string = bufferedReader.readLine()) != null) {
                stringBuilder.append(json_string + "\n");
            }

            bufferedReader.close();
            inputstream.close();
            httpURLConnection.disconnect();
            return stringBuilder.toString().trim();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        super.onProgressUpdate(values);
    }

    @Override
    protected void onPostExecute(String result) {
        Log.d("haha", "hehe");
        json_result = result;
    }

    public String getResult() {
        return json_result;
    }

Here is my logcat:

FATAL EXCEPTION: main 
Process: com.example.aaa.bbb, PID: 5680
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.aaa.bbb/com.example.aaa.bbb.Games}: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)

Upvotes: 2

Views: 3398

Answers (3)

sivaBE35
sivaBE35

Reputation: 1891

Another way you can place intent inside your post execute. in your Activity's onCreate method

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

    new RetrieveGamesBGTask(Splash.this).execute();

}

now in your RetrieveGamesBGTask's onPostExecute method

@Override
protected void onPostExecute(String result) {
    Log.d("haha", "hehe");
    json_result = result;
    Intent intent = new Intent(context, Games.class);
                intent.putExtra("json_data", json_string);
                intent.putExtra("json_data",json_result);
                context.startActivity(intent);
}

Upvotes: 1

Raymond
Raymond

Reputation: 2372

There's a couple of things you could do better here. But your main problem is that you are doing async tasks(backgroundtask) and not handling a proper callback.

What happens in the following:

  1. Starting of the async task.
  2. You sleep for 3 seconds (Which is probably to try to make the async finish before the code continues.)
  3. The Async task might not have finish have finished in the 3 seconds.
  4. Your try to parse the JSON that has not been received yet.
  5. This throws a nullpointer.

Now while crashing the async task still runs and finishes. I'm not sure if you save this JSON and then it becomes readable while completing and becomes available the second time, or that the second time the task might finish within 3 seconds.

What you should do

  1. Starting of the async task.
  2. Do Not let the thread sleep.
  3. In the async task onPostExecute have a callback to your main thread.
  4. Have the callback return the JSON obtained from the task.
  5. Now parse the JSON you will have, if the call itself did succeed.

To achieve this look here https://developer.android.com/training/best-background.html

It should provide enough information to get this piece of code stable.

Upvotes: 7

RvdK
RvdK

Reputation: 19800

Well the error is quite clear:

Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference

So somewhere you call length on a not initialized string. This is not in the code you posted. (only jsonArray.length())

Upvotes: -1

Related Questions