-2

I'm currently getting a NullPointerException in my android app caused by "attempt to invoke method on a null Object". Here is my code:

Logcat says the Exception is thrown in the onCreate part in MovieGridFragment on the line "movieGridFragment.setSelection(pos)".

public class MovieGridFragment extends Fragment {

public clickInterfaceHelper clickListener;
private int index;
private GridView movieGridView;
public List<movieData> movieDataList = new ArrayList<>();

public MovieGridFragment() {} //empty constructor

@Override
public void onAttach(Context context) {
    this.clickListener = (clickInterfaceHelper) context;
    super.onAttach(context);
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    if(savedInstanceState != null) {
    int pos = (Integer) savedInstanceState.getSerializable("POS");
        if (!movieDataList.isEmpty()) {
            movieDataList = Arrays.asList((movieData[]) savedInstanceState.getSerializable("OLDMOVIEDATA"));
        }
       movieGridView.setSelection(pos);
    }
    super.onCreate(savedInstanceState);
}


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        setHasOptionsMenu(true);
    
    
        View rootView = inflater.inflate(R.layout.movie_display_fragment, container, false);
    
        movieGridView = (GridView) rootView.findViewById(R.id.gv_movie_display);
        movieAdapter adapter = new movieAdapter(getActivity(),movieDataList);
        adapter.notifyDataSetChanged();
        movieGridView.setAdapter(adapter);
        movieGridView.setSelection(index);
        movieGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if(clickListener != null)
                        clickListener.clickOnItem(position);
    
            }
        });
        return rootView;
    }
    
    @Override
    public void onSaveInstanceState(Bundle outState) {
        index = movieGridView.getFirstVisiblePosition();
        outsate.putSerializable("POS",index);
        outState.putSerializable("OLDMOVIEDATA",movieData.movieDataArray);
        super.onSaveInstanceState(outState);
    }}

and mainactivity:

public class MainActivity extends AppCompatActivity implements clickInterfaceHelper {

public static String sorterString = null;
public static String urlBase = "https://api.themoviedb.org/3/movie/";
public static String urlFinal = null;

RequestQueue requestQueue;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if(savedInstanceState == null) {
                getSupportFragmentManager().beginTransaction()
                .add(R.id.activity_container, new MovieGridFragment())
                .commit();
        movieData.movieDataPosition = 0;
    }
    if(savedInstanceState != null) {
        sorterString = savedInstanceState.getString("SORTER");
    }

    if(savedInstanceState == null)
        movieData.movieDataPosition = 0;

    if(sorterString==null)
        sorterString="popular?";
    if(sorterString!="favorite" && sorterString!=null) {
        if(networkChecker.isNetworkAvailableChecker(this)) {
            movieRequest();
        }
    }



}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu_act, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    if(id == R.id.m_popularity_action) {
        if(sorterString != "popular?") {
            sorterString = "popular?";
            if(networkChecker.isNetworkAvailableChecker(this))
            movieRequest();
        }
        return true;
    }

    if(id == R.id.m_action_voter) {
        if(sorterString != "top_rated?") {
            sorterString = "top_rated?";
            if(networkChecker.isNetworkAvailableChecker(this))
            movieRequest();
        }
        return true;
    }

    if(id == R.id.m_favorite_btn) {
        if(sorterString != "favorite") {
            SQLiteOpenHelper helper = new movieDataDbHelper(this);
            SQLiteDatabase database = helper.getReadableDatabase();
            Cursor cursor= database.query(movieDataContract.contractEntry.TABLE_NAME,
                    new String[] {
                            movieDataContract.contractEntry.ID,
                            movieDataContract.contractEntry.IMG_PATH},null,null,null,null,null);
            if(cursor.getCount() == 0) {
                Toast.makeText(this, "there are no favorite movies yet!",Toast.LENGTH_SHORT).show();
            } else {
                sorterString = "favorite";
                showFavoriteFragment();
            }
            database.close();
            helper.close();
            cursor.close();
        }
        return true;
    }
    return super.onOptionsItemSelected(item);
}

public void showFavoriteFragment() {
    favoriteMoviesDetailsFragment fragment = new favoriteMoviesDetailsFragment();
    try {
        getFragmentManager().beginTransaction().replace(R.id.activity_container,fragment).commit();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
    outState.putString("SORTER", sorterString);
    outState.putInt("POSITION",movieData.movieDataPosition);
    super.onSaveInstanceState(outState, outPersistentState);
}

public void movieRequest() {
        urlFinal = urlBase + sorterString + movieData.apiKey;
        urlFinal.trim();
        requestQueue = Volley.newRequestQueue(this);
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, urlFinal, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                try {
                    JSONArray array = response.getJSONArray("results");
                    movieData.movieDataArray = new movieData[array.length()];

                    for (int i = 0; i < array.length(); i++) {
                        movieData movie = new movieData();
                        JSONObject jsonObject = array.getJSONObject(i);
                        //movie.setPosition(i);
                        movie.setMovieId(jsonObject.getString("id"));
                        movie.setMovieImagePath(jsonObject.getString("poster_path"));
                        movie.setMovieTitle(jsonObject.getString("original_title"));
                        movie.setMoviePlot(jsonObject.getString("overview"));
                        movie.setMovieVoting(jsonObject.getString("vote_average"));
                        movie.setMovieReleaseDate(jsonObject.getString("release_date"));
                        movieData.movieDataArray[i] = movie;
                    }

                    MovieGridFragment gridFragment = new MovieGridFragment();
                    gridFragment.movieDataList = Arrays.asList(movieData.movieDataArray); //hier wird datalist eigentlich zugewiesen
                    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                    transaction.replace(R.id.activity_container, gridFragment);
                    try {
                        transaction.commitAllowingStateLoss();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("volley", String.valueOf(error));
            }
        }
        );
        requestQueue.add(jsonObjectRequest);

}

@Override
public void clickOnItem(int id) {
    movieData.movieDataPosition = id;
    if(movieData.movieDataArray == null) {
        movieRequest();
    } else {
        Intent intent = new Intent(this, detailsActivity.class);
        intent.putExtra("FRAGMENT","MOVIE");
        startActivity(intent);
    }

}

@Override
public void favoriteMovieItem(int movieId) {
    movieData.dbPosition = movieId;

    Intent intent = new Intent(this,detailsActivity.class);
    intent.putExtra("FRAGMENT","favorite");
    startActivity(intent);
} }

LogCat:

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.popularmoviesapp/com.example.android.popularmoviesapp.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.GridView.setSelection(int)' on a null object reference
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
 at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4483)
 at android.app.ActivityThread.-wrap19(ActivityThread.java)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1466)
 at android.os.Handler.dispatchMessage(Handler.java:102)
 at android.os.Looper.loop(Looper.java:154)
 at android.app.ActivityThread.main(ActivityThread.java:6077)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
                                                                                     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.GridView.setSelection(int)' on a null object reference
 at com.example.android.popularmoviesapp.MovieGridFragment.onCreate(MovieGridFragment.java:48)
 at android.support.v4.app.Fragment.performCreate(Fragment.java:2172)
 at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1243)
 at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1523)
 at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1585)
 at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:2827)
 at android.support.v4.app.FragmentController.dispatchCreate(FragmentController.java:190)
 at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:353)
 at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:88)
 at com.example.android.popularmoviesapp.MainActivity.onCreate(MainActivity.java:46)
 at android.app.Activity.performCreate(Activity.java:6662)
 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 
 at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4483) 
 at android.app.ActivityThread.-wrap19(ActivityThread.java) 
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1466) 
 at android.os.Handler.dispatchMessage(Handler.java:102) 
 at android.os.Looper.loop(Looper.java:154) 
 at android.app.ActivityThread.main(ActivityThread.java:6077) 
General Grievance
  • 4,555
  • 31
  • 31
  • 45
Torben
  • 558
  • 2
  • 7
  • 16

2 Answers2

0

Fragment's aren't exactly like activities.

You've referenced a View (movieGridView) before onViewCreated has happened, and thus it must be `null.

See here

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(savedInstanceState != null) {
        int pos = (Integer) savedInstanceState.getSerializable("POS");
        if (!movieDataList.isEmpty()) {
            movieDataList = Arrays.asList((movieData[]) savedInstanceState.getSerializable("OLDMOVIEDATA"));
        }
       // movieGridView.setSelection(pos); // You can't do this here!
    }

}

Besides that, you do not need onCreate at all. savedInstanceState is available within onCreateView.

So, remove that method, and move the code around.

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    setHasOptionsMenu(true);

    // Added this section
    if (movieDataList == null) {
        movieDataList = new ArrayList<movieData>();
    }

    if (savedInstanceState != null) {
        index = (Integer) savedInstanceState.getSerializable("POS");

        // Not sure why you had 'not empty'
        if (movieDataList.isEmpty()) {
            movieDataList.addAll(Arrays.asList((movieData[]) savedInstanceState.getSerializable("OLDMOVIEDATA"));
        }
    } // End restore instance state


    View rootView = inflater.inflate(R.layout.movie_display_fragment, container, false);

    movieGridView = (GridView) rootView.findViewById(R.id.gv_movie_display);
    movieAdapter adapter = new movieAdapter(getActivity(),movieDataList);
    movieGridView.setAdapter(adapter);
    movieGridView.setSelection(index);

    return rootView;
}

You probably want to Bundle.putIntExtra for the "POS", but that is personal preference.

And you should also make MovieData be a Parcelable when you get a chance.

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • thank you very much, this fixed the NullPointerException! Great explanation. The setSelection method doesn't set the position right now though, got to fix that now! – Torben Mar 09 '17 at 19:17
  • You had `pos` and `index`. Wasn't sure how to handle that – OneCricketeer Mar 09 '17 at 19:29
  • i save index in the savebundle now with putint and get it in oncreateview with getInt and then use smoothscrolltoposition but it doesn't scroll – Torben Mar 09 '17 at 21:08
  • Not sure what to tell you, but that is a different issue. If you have a new question, please ask it by clicking the [Ask Question](//stackoverflow.com/questions/ask) button. – OneCricketeer Mar 09 '17 at 21:44
-2

initialise

private int index=0;

Since index is not initialised it will be a null value and cause the crash

g7pro
  • 817
  • 1
  • 6
  • 11