Android 中的 NullPointerException setSelection 微调器

NullPointerException setSelection spinner in Android

如果用户之前选择了书 "Hamlet",在新的编辑 activity 中,我希望已经在 "Hamlet" 处选择了微调器,然后他们可以根据需要更改它到,但我收到此错误消息:

NullPointerException 尝试在空对象引用

上调用 ArrayAdapter.getPosition

在下面的代码中,retrieveAndSetData() 应该获取数据库中选定的书籍以显示在微调器上,prepareListOfBooks() 应该使用当前用户的所有书籍填充同一个微调器以进行更新操作

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

}

第 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) {

        }
    });
}

拜托,我的代码有什么问题?

编辑 1

我更改了代码,但仍然出现相同的错误。这是我更改的内容以及之前未显示的更多详细信息:

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

您的 bookValue 或 bookId 超出范围。也许您想像索引一样使用它,但 id 超出了列表范围

首先你要传递一个字符串作为位置,它应该是一个整数

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

然后你使用这个值作为位置,你确定id是有序的并且不大于size-1吗?

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

这意味着 bookAdaptnull。您使用 bookAdapt = (ArrayAdapter) bookListSpinner.getAdapter(); 初始化它,因此很可能您没有在 bookListSpinner.

上正确设置适配器

您在此处粘贴的代码没有显示您声明和初始化的位置 bookListSpinner 也没有显示您创建适配器以设置它的位置。但是,在您的 onDataChange() 事件处理程序中,您有:

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

每次 onDataChange() 事件触发时 这会从布局中获取微调器小部件并为其创建一个新的适配器 。在此本地声明的微调器引用上设置适配器不会影响您在其他地方声明的任何其他引用。

此外,在每个事件上创建一个新适配器可能会导致性能问题,因为它每次都会为微调器重建所有视图。相反,您应该在 onCreate() 中为 activity (或 onCreateView() 如果您有片段)创建一次适配器。然后您只需更新适配器的数据,而不是每次都创建一个全新的适配器。

使用此技术还将确保您拥有可用于正确适配器的正确微调器对象。事实上,您可以只保留对适配器的引用,因此根本不需要调用 getAdapter()

问题与 Firebase 如何异步处理我的数据有关。当我试图访问

上的 ArrayAdapter 时
 bookAdapt = (ArrayAdapter) bookListSpinner.getAdapter();

我收到一个空指针,因为 ArrayAdapter 还没有准备好。为了解决这个问题,我遵循了这个