0

So I'm working on a personal app that displays JSON data using CardView and RecycleView, however I'm constantly getting this NullPointerException and I have no idea how I should approach to debug this and I could really use some help.

These are the errors I'm getting

    {java.lang.RuntimeException: Unable to start activity ComponentInfo{com.brokenbroadcast.nba_project/com.brokenbroadcast.nba_project.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.brokenbroadcast.nba_project.NBA.getGameList()' on a null object reference
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3149)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3257)
  at android.app.ActivityThread.access$1000(ActivityThread.java:197)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1681)
  at android.os.Handler.dispatchMessage(Handler.java:102)
  at android.os.Looper.loop(Looper.java:145)
  at android.app.ActivityThread.main(ActivityThread.java:6891)
  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:1404)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
  at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:115)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.brokenbroadcast.nba_project.NBA.getGameList()' on a null object reference
  at com.brokenbroadcast.nba_project.MainActivity.onCreate(MainActivity.java:52)
  at android.app.Activity.performCreate(Activity.java:6550)
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1120)
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3102)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3257) 
  at android.app.ActivityThread.access$1000(ActivityThread.java:197) 
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1681) 
  at android.os.Handler.dispatchMessage(Handler.java:102) 
  at android.os.Looper.loop(Looper.java:145) 
  at android.app.ActivityThread.main(ActivityThread.java:6891) 
  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:1404) 
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)

From my understanding it is having problem with my code at MainActivity.java:52. Here is my MainActivity.java

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

private List<Game> gameList;
private NBA mNBA;
public static final String TAG = MainActivity.class.getSimpleName();
public static final String mScoreboardUrl = "http://data.nba.com/5s/json/cms/noseason/scoreboard/20160116/games.json";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.content_main);
    RecyclerView recList = (RecyclerView) findViewById(R.id.cardList);
    recList.setHasFixedSize(true);
    LinearLayoutManager llm = new LinearLayoutManager(this);
    llm.setOrientation(LinearLayoutManager.VERTICAL);
    recList.setLayoutManager(llm);
    gameList = new ArrayList<Game>();
    setUpGames();

    GameAdapter ca = new GameAdapter(mNBA.getGameList());
    recList.setAdapter(ca);
}



private void setUpGames() {
    if (isNetworkAvailable()) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(mScoreboardUrl).build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                alertUserAboutError();
            }

            @Override
            public void onResponse(Response response) throws IOException {
                try {
                    String jsonData = response.body().string();
                    if (response.isSuccessful()) {
                        mNBA = parseNBADetails(jsonData);
                    } else {
                        alertUserAboutError();
                    }
                } catch (IOException e) {
                } catch (JSONException j) {
                }
            }
        });
    } else {
        Toast.makeText(this, getString(R.string.network_unavailable_message),
                Toast.LENGTH_LONG).show();
    }
}


private void alertUserAboutError() {
    AlertDialogFragment dialog = new AlertDialogFragment();
    dialog.show(getFragmentManager(), "error_dialog");
}

private boolean isNetworkAvailable() {
    ConnectivityManager manager = (ConnectivityManager)
            getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = manager.getActiveNetworkInfo();
    boolean isAvailable = false;
    if (networkInfo != null && networkInfo.isConnected()) {
        isAvailable = true;
    }

    return isAvailable;

}

private NBA parseNBADetails(String jsonData) throws JSONException {

    NBA nba = new NBA();
    nba.setGameList(parseGames(jsonData));

    return nba;
}

private List<Game> parseGames(String jsonData) throws JSONException {
    JSONObject sports_content = new JSONObject(jsonData);
    JSONObject schedule = sports_content.getJSONObject("sports_content");
    JSONObject gameArray = schedule.getJSONObject("games");
    JSONArray data = gameArray.getJSONArray("game");

    List<Game> gameList = new ArrayList<Game>();
    for (int i = 0; i < data.length(); i++) {
        Game game = new Game();
        JSONObject jsonGame = data.getJSONObject(i);

        JSONObject jsonVisitor = jsonGame.getJSONObject("visitor");
        game.setVisitorTeamName(jsonVisitor.getString("nickname"));
        game.setVisitorScore(jsonVisitor.getInt("score"));
        game.setVisitorTeamLocation(jsonVisitor.getString("city"));

        JSONObject jsonHome = jsonGame.getJSONObject("home");
        game.setHomeTeamLocation(jsonHome.getString("city"));
        game.setHomeTeamName(jsonHome.getString("nickname"));
        game.setHomeScore(jsonHome.getInt("score"));

        Log.i(TAG, game.getHomeScore() + "");

        gameList.add(game);
    }
    return gameList;
}
}

This is my class NBA.java

public class NBA {
private List<Game> mGameList;

public List<Game> getGameList() {
    return mGameList;
}

public void setGameList(List<Game> gameList) {
    mGameList = gameList;
}
}

This is my Game.java

public class Game {


    private int mHomeScore;
    private int mVisitorScore;
    private String mHomeTeamLocation;
    private String mHomeTeamName;
    private String mVisitorTeamLocation;
    private String mVisitorTeamName;


    public String getHomeTeamLocation() {
        return mHomeTeamLocation;
    }

    public Game(){}

    public void setHomeTeamLocation(String homeTeamLocation) {
        mHomeTeamLocation = homeTeamLocation;
    }

    public String getHomeTeamName() {
        return mHomeTeamName;
    }

    public void setHomeTeamName(String homeTeamName) {
        this.mHomeTeamName = homeTeamName;
    }

    public String getVisitorTeamLocation() {
        return mVisitorTeamLocation;
    }

    public void setVisitorTeamLocation(String visitorTeamLocation) {
        mVisitorTeamLocation = visitorTeamLocation;
    }

    public String getVisitorTeamName() {
        return mVisitorTeamName;
    }

    public void setVisitorTeamName(String visitorTeamName) {
        mVisitorTeamName = visitorTeamName;
    }


    public String getTitle() {
        return getHomeTeam() + " vs. " + getVisitorTeam();
    }

    public String getHomeTeam() {

        return mHomeTeamLocation+" " +mHomeTeamName;
    }

    public String getVisitorTeam() {
        return mVisitorTeamLocation+" "+mVisitorTeamName;
    }


    public int getHomeScore() {
        return mHomeScore;
    }

    public void setHomeScore(int homeScore) {
        mHomeScore = homeScore;
    }

    public int getVisitorScore() {
        return mVisitorScore;
    }

    public void setVisitorScore(int visitorScore) {
        mVisitorScore = visitorScore;
    }


}

My GameAdapter.java

    package com.brokenbroadcast.nba_project;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by steven on 1/16/2016.
 */
public class GameAdapter extends RecyclerView.Adapter<GameAdapter.GameViewHolder> {

    private List<Game> mGameList = new ArrayList<Game>();

    public GameAdapter(List<Game> gameList){
        mGameList=gameList;
    }

    @Override
    public GameViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view, parent, false);
        return new GameViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(GameViewHolder holder, int position) {
        Game curGame = mGameList.get(position);

        holder.vHomeScore.setText(curGame.getHomeScore()+"");
        holder.vVisitorScore.setText(curGame.getVisitorScore()+"");
        holder.vTitle.setText(curGame.getTitle());
        holder.vVisitorTeam.setText(curGame.getVisitorTeam());
    }

    @Override
    public int getItemCount() {
        return mGameList.size();
    }

    public class GameViewHolder extends RecyclerView.ViewHolder {
        private TextView vHomeTeam;
        private TextView vVisitorTeam;
        private TextView vTitle;
        private TextView vHomeScore;
        private TextView vVisitorScore;


        public GameViewHolder(View v) {
            super(v);
            vHomeTeam = (TextView) v.findViewById(R.id.homeTeam);
            vVisitorTeam = (TextView) v.findViewById(R.id.visitorTeam);
            vHomeScore = (TextView) v.findViewById(R.id.homeScore);
            vVisitorScore = (TextView) v.findViewById(R.id.visitorScore);
            vTitle = (TextView) v.findViewById(R.id.gameTitle);
        }
    }
}

If anyone could help me I will really appreciate it.

steven shin
  • 1
  • 1
  • 1

2 Answers2

0

In the following line you are trying to access a list which has never been initialized.

GameAdapter ca = new GameAdapter(mNBA.getGameList());

Make sure mNBA is not null. You only declare the variable but never assigned any value to it.

Also declare :

private NBA mNBA = new NBA();
Pritam Banerjee
  • 17,953
  • 10
  • 93
  • 108
  • Do you know why it is null? It seems like it should be initialized at 'mNBA = parseNBADetails(jsonData);' I know my parsing steps work by debugging and displaying its value via log but when it comes to initializing the value mNBA it just does not seem to work. – steven shin Jan 17 '16 at 19:26
  • Declare mnBA like this private NBA mNBA = new NBA(); – Pritam Banerjee Jan 17 '16 at 19:32
0

It looks like the assignment mNBA = parseNBADetails(jsonData); doesn't take place on the same thread as GameAdapter ca = new GameAdapter(mNBA.getGameList());, so mNBA may still be null when the latter statement is called.

A possible solution is to put that statement in the same thread that initializes mNBA :

        public void onResponse(Response response) throws IOException {
            try {
                String jsonData = response.body().string();
                if (response.isSuccessful()) {
                    mNBA = parseNBADetails(jsonData);
                    GameAdapter ca = new GameAdapter(mNBA.getGameList()); // moved from onCreate
                    recList.setAdapter(ca); // moved from onCreate
                } else {
                    alertUserAboutError();
                }
            } catch (IOException e) {
            } catch (JSONException j) {
            }
        }
Eran
  • 387,369
  • 54
  • 702
  • 768
  • I think you are right because when I put Log right after my setUpGames(), it tells me that my mNBA.getGameList() is empty. But when I put the Log right after mNBA = parseNBADetails(), the list is not empty. It seems like the gameAdapter is retrieving the gameList before actually initializing it by setUpGames(). Is there any documentation on Android on this? Why is the gameAdapter using the mNBA before it actually goes through setUpGames()? – steven shin Jan 17 '16 at 19:56