0

If a user picked the book "Hamlet" previously, in the new edit activity I want the spinner to be already selected at "Hamlet" and then they can change this if they want to but i'm getting this error message:

NullPointerException Attempt to invoke ArrayAdapter.getPosition on a null object reference

In the code bellow, retrieveAndSetData() should get the selected book on database to show on spinner and prepareListOfBooks() should populate the same spinner with all books of current user for update action

step 1

 private void retrieveAndSetData(Library l){

    library = l;

    prepareListOfBooks();

    String bookValue = library.getBookId();
    ArrayAdapter bookAdapt;
    int bookSpinnerPosition;

    bookAdapt = (ArrayAdapter) bookListSpinner.getAdapter();
    bookSpinnerPosition = bookAdapt.getPosition(bookValue);
    bookListSpinner.setSelection(bookSpinnerPosition);

}

step 2

private void prepareListOfBooks(){
    database = FirebaseDatabase.getInstance().getReference("books");
    account = GoogleSignIn.getLastSignedInAccount(this);
    firebaseUser = account.getId();
    query = database.orderByChild("ownerId").equalTo(firebaseUser);

    query.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            final List<String> books = new ArrayList<String>();

            for (DataSnapshot bookSnapshot: dataSnapshot.getChildren()) {
                String bookName = bookSnapshot.child("name").getValue(String.class);
                books.add(bookName);
            }

            Spinner bookSpinner = (Spinner) findViewById(R.id.bookListSpinner);
            ArrayAdapter<String> booksAdapter = new ArrayAdapter<String>(EditBookActivity.this, android.R.layout.simple_spinner_item, books);
            booksAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            bookSpinner.setAdapter(booksAdapter);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

Please, what is wrong with my code?

EDIT 1

I changed my code but still get the same error. Here what i changed and some more details that i didn't show before:

public class EditBookActivity extends AppCompatActivity {
    Spinner bookListSpinner;
}



protected void onCreate(Bundle savedInstanceState) {
      ....
      prepareListOfBooks();
       ...
      bookListSpinner = (Spinner) findViewById(R.id.bookListSpinner);
}

private void prepareListOfBooks(){
    database = FirebaseDatabase.getInstance().getReference("books");
    account = GoogleSignIn.getLastSignedInAccount(this);
    firebaseUser = account.getId();
    query = database.orderByChild("ownerId").equalTo(firebaseUser);

    query.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            final List<String> books = new ArrayList<String>();

            for (DataSnapshot bookSnapshot: dataSnapshot.getChildren()) {
                String bookName = bookSnapshot.child("name").getValue(String.class);
                books.add(bookName);
            }

            ArrayAdapter<String> booksAdapter = new ArrayAdapter<String>(EditBookActivity.this, android.R.layout.simple_spinner_item, books);
            booksAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            //changed the line bellow, i dont create a new spinner variable, i use the same variable that is declared in the begining of this class
            bookListSpinner.setAdapter(booksAdapter); 
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

 private void retrieveAndSetData(Library l){
        library = l;

        String bookValue = library.getBookName();
        ArrayAdapter bookAdapt;
        int bookSpinnerPosition;

        bookAdapt = (ArrayAdapter) bookListSpinner.getAdapter(); //null pointer is here
        bookSpinnerPosition = bookAdapt.getPosition(bookValue);
        bookListSpinner.setSelection(bookSpinnerPosition);
}
Liam Park
  • 414
  • 1
  • 9
  • 26

4 Answers4

1

your bookValue or bookId is out of range. maybe you want to use it like index but the id is out of the list range

hamed
  • 148
  • 11
  • Hello, thanks for your answer. The id in this case is the book's name itself (bookValue). I tried to print bookAdapt.getCount() but returned the same message of NullPointerException – Liam Park Oct 28 '19 at 21:47
1

The line that causes the error: bookSpinnerPosition = bookAdapt.getPosition(bookValue);

This means that bookAdapt is null. You initialize it with bookAdapt = (ArrayAdapter) bookListSpinner.getAdapter();, so most likely you have not correctly set the adapter on bookListSpinner.

The code you pasted here doesn't show where you declare and initialize bookListSpinner nor where you create an adapter to set to it. However, in your onDataChange() event handler you have:

Spinner bookSpinner = (Spinner) findViewById(R.id.bookListSpinner);
ArrayAdapter<String> booksAdapter = new ArrayAdapter<String>(EditBookActivity.this, android.R.layout.simple_spinner_item, books);

This gets the spinner widget from the layout and creates a new adapter for it every time the onDataChange() event fires. Setting the adapter on this locally declared spinner reference does not affect any other references that you have declared elsewhere.

Also, creating a new adapter on each event has the potential to cause performance issues because it rebuilds all of the views for the spinner each time. Instead, you should create the adapter once in onCreate() for the activity (or onCreateView() if you have a fragment). Then you only update the data for the adapter instead of creating a whole new adapter each time.

Using this technique will also ensure that you have the correct spinner object available with the correct adapter. In fact, you can just keep a reference to the adapter, so you don't need to call getAdapter() at all.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • Thanks for your answer. I changed my code trying to follow what you said but still get the same error. I updated my question with this new attempt, can you check? Thank you! – Liam Park Oct 29 '19 at 01:40
0

first of all you are passing a string for position, which should be an integer

 String bookValue = library.getBookId();
 bookSpinnerPosition = bookAdapt.getPosition(bookValue);

and then you are using this value as a position, are you sure that the ids are in order and not greater than the size-1?

Haider Saleem
  • 773
  • 1
  • 9
  • 17
  • Hello, thanks for your answer. I thought doing something like: retrieve all books of current user, add each retrieved book in a list, use this list to pass the selected book position as parameter on getPosition (). What do you think? – Liam Park Oct 28 '19 at 21:45
  • Also, I tried to print bookAdapt.getCount() but returned the same message of NullPointerException – Liam Park Oct 28 '19 at 21:48
  • Ok, so now u need to iterate through your booklist and match the bookid to get the selected book index, and then set that index to your sp.setselection. – Haider Saleem Oct 28 '19 at 21:55
  • I tried this way and sadly didn't work, the size of the list was 0 and i didn't understand why because in some moment was populated correctly – Liam Park Oct 29 '19 at 01:37
0

The problem was related about how Firebase asynchronously handled my data. When I was trying to access ArrayAdapter on

 bookAdapt = (ArrayAdapter) bookListSpinner.getAdapter();

I was receiving a null pointer because the ArrayAdapter was not ready yet. To resolve, I followed this solution:

Liam Park
  • 414
  • 1
  • 9
  • 26