Получение ошибки нулевой ссылки на объект в Android после инициализации объекта

#java #android #android-fragments

#java #Android #android-фрагменты

Вопрос:

Это то, что делает мой код:

MainActivity передает объект «device», используя намерения ItemListActivity:

 // When button is clicked to go to ItemListActivity
car = new Car();
device = new Device(car);
intent.putExtra("device", device);
  

Объект устройства имеет объект Car в качестве поля, и оба реализуют сериализуемость.

Теперь Car также является классом fragment, и поэтому в ItemListActivity я хотел бы иметь возможность открывать фрагмент car в объекте device, который был передан через intent. (Это действие потока master / detail)

ItemListActivity:

 // in onCreate //
Intent intent = getIntent();
Device device = (Device) intent.getSerializableExtra("device");

View recyclerView = findViewById(R.id.item_list);
assert recyclerView != null;
setupRecyclerView((RecyclerView) recyclerView);
//////////////////

private void setupRecyclerView(@NonNull RecyclerView recyclerView) {
    recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(this, ItemsContent.ITEMS, mTwoPane, device));
}

public static class SimpleItemRecyclerViewAdapter
        extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> {
    ...
    private Device mDevice;

    // Here's the problem:
    Car car = mDevice.getCar(); // getCar just returns the private Car field in Device

    private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            ItemsContent.ItemsPage item = (ItemsContent.ItemsPage) view.getTag();
            if (mTwoPane) {
                Bundle arguments = new Bundle();
                arguments.putString(ItemDetailFragment.ARG_ITEM_ID, item.id);

                Fragment fragment;
                fragment = car;
                mParentActivity.getSupportFragmentManager().beginTransaction().replace(R.id.item_detail_container, fragment).commit();
                ...
            }
        }
    ...
    SimpleItemRecyclerViewAdapter(ItemListActivity parent,
                                  List<ItemsContent.ItemsPage> items,
                                  boolean twoPane, Device device) {
        mValues = items;
        mParentActivity = parent;
        mTwoPane = twoPane;
        mDevice = device;
    }
}
  

(Большая часть кода — это просто заполнитель / детализация потока операций, но дайте мне знать, если вы тоже хотите это увидеть)

Ошибка, которую я получаю, когда пытаюсь открыть ItemListActivity из main:

 java.lang.NullPointerException: Attempt to invoke virtual method 'Device.getCar()' on a null object reference
  

Но я действительно не понимаю, почему это происходит, потому что даже я просто установил car = null, мое приложение работает до тех пор, пока я не введу ItemListActivity и не выберу фрагмент Car. Затем приложение выходит из строя, но я не понимаю, как установка car = mDevice.getCar() не позволяет моему приложению даже перейти к ItemListActivity из main , и поэтому я не понимаю, почему я получаю ошибку null при попытке открыть ItemListActivity. Спасибо!

редактировать: добавлен код конструктора

Комментарии:

1. Вы объявляете mDevice, и оно равно нулю private Device mDevice; . В самой следующей строке кода вы пытаетесь вызвать метод для этого нулевого объекта Car car = mDevice.getCar(); , чтобы получить NPE..

2. О, я забыл опубликовать конструктор, но в setUpRecyclerView устройство является параметром, и вызывается mDevice = device

3. Не имеет значения, поскольку вы писали mDevice.getCar(); вне конструктора. Если приведенный вами пример кода не отражает фактическую ситуацию, вам необходимо обновить вопрос.

4. Отредактировано, чтобы добавить конструктор в этот класс. Итак, когда я вызываю setUpRecyclerView, не установит ли конструктор сначала mDevice = device, а затем продолжит код? Как я должен назначить mDevice перед вызовом getCar()? @takendarkk

5. «не будет ли конструктор сначала устанавливать mDevice = device » Нет, это происходит после mDevice.getCar(); , поскольку это было написано на уровне класса, а не внутри метода. Просто примите вызов метода, который выдает NPE, и поместите его в свой конструктор в конце — нет необходимости, чтобы он был на уровне класса.