Нулевая ссылка на объект для интерфейса / пакета - PullRequest
0 голосов
/ 27 июня 2019

У меня есть экран, на котором я собираю информацию об оплате. Здесь пользователь может либо нажать кнопку «Назад», чтобы внести изменения в свой заказ на покупку в ShopFragment, либо нажать кнопку «Отправить», чтобы перейти к ConfirmationFragment. Кнопка «Назад» работает нормально, но кнопка «Отправить» приводит к этой ошибке:

06-27 01:07:38.321 14771-14771/com.shop.away E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.shop.away, PID: 14771
    java.lang.NullPointerException: Attempt to invoke interface method 'void com.shop.away.ui.PaymentFragment$OnPaymentSubmitListener.onPaymentSubmit(android.os.Bundle)' on a null object reference
        at com.shop.away.ui.PaymentFragment$7.onSuccess(PaymentFragment.java:294)
        at com.shop.away.ui.PaymentFragment$7.onSuccess(PaymentFragment.java:289)
        at com.google.android.gms.tasks.zzn.run(Unknown Source)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:158)
        at android.app.ActivityThread.main(ActivityThread.java:7224)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

Вот код для PaymentFragment :

private OnPaymentSubmitListener paymentSubmitListener;

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment

        paymentView = inflater.inflate(R.layout.fragment_payment, container, false);

btnBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                bundle.putBoolean("direction", false);
                paymentSubmitListener.onPaymentSubmit(bundle);
            }
        });

        btnPlaceOrder.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                getToken();
            }
        });
        return paymentView;
    }

private void getToken() {
// If token obtained successfully place order
}

private void placeOrder() {
if (orderPlaced.isSuccessful) {
bundle.putBoolean("direction", true);
                paymentSubmitListener.onPaymentSubmit(bundle);
}

public void onButtonPressed(Bundle bundle) {
        if (paymentSubmitListener != null) {
            paymentSubmitListener.onPaymentSubmit(bundle);
        }
    }

    @Override
    public void onAttach(Context context) {
        paymentContext = context;
        super.onAttach(paymentContext);
        if (context instanceof OnPaymentSubmitListener) {
            paymentSubmitListener = (OnPaymentSubmitListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        paymentSubmitListener = null;
    }

    public interface OnPaymentSubmitListener {
        void onPaymentSubmit(Bundle bundle);
    }
}

И в моей MainActivity вот как я работаю с интерфейсом:

public void onPaymentSubmit(Bundle bundle) {
        if (bundle != null && bundle.containsKey("direction")) {
            Boolean direction = bundle.getBoolean("direction");
            if (!direction) {
                ShopFragment fragment = new ShopFragment();
                openFragment(bundle, fragment, direction);
            } else {
                ConfirmationFragment fragment = new ConfirmationFragment();
                openFragment(bundle, fragment, direction);
            }
        }
    }

private void openFragment(Bundle bundle, Fragment fragment, Boolean direction) {
// Open corresponding fragment using animation
}

PaymentFragment.java: 294 относится именно к этой строке здесь: paymentSubmitListener.onPaymentSubmit (bundle)

1 Ответ

0 голосов
/ 27 июня 2019

инициализируйте слушателя в onCreateView() и добавьте проверку

if(paymentSubmitListener != null)

перед использованием.

Вы получаете нулевой указатель, потому что при возврате к предыдущему фрагменту слушатель не инициализируется, потому что onAttach (Контекст контекста) вызывается только тогда, когда фрагмент присоединен, а когда вы возобновляете его, он все еще присоединен, но инициализация поля слушателя пропала.

попробуйте переместить эту часть

  if (context instanceof OnPaymentSubmitListener) {
            paymentSubmitListener = (OnPaymentSubmitListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
}

в public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

Кстати, я бы предложил переосмыслить вашу архитектуру, потому что я не думаю, что это хорошая практика - использовать контекст в качестве экземпляра слушателя. Лучше сделать так, чтобы Fragment реализовал слушатель и использовал его как this.

Другая мысль состоит в том, что Context во фрагменте может быть null.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...