简体   繁体   中英

NullPointerException setSelection spinner in Android

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);
}

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

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.

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?

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 :

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