bluelinelabs / Conductor

A small, yet full-featured framework that allows building View-based Android applications
Apache License 2.0
3.9k stars 343 forks source link

Fatal Exception: java.lang.NullPointerException #596

Closed TikTak123 closed 4 years ago

TikTak123 commented 4 years ago

Conductor version: implementation 'com.bluelinelabs:conductor:3.0.0-rc2'

API level: Android 5, 6, 7, 8, 9, 10

Error log:

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.bluelinelabs.conductor.d.V0()' on a null object reference
       at com.bluelinelabs.conductor.ControllerHostedRouter.getSiblingRouters(ControllerHostedRouter.java:224)
       at com.bluelinelabs.conductor.Router.removeAllExceptVisibleAndUnowned(Router.java:871)
       at com.bluelinelabs.conductor.Router.setBackstack(Router.java:412)
       at com.bluelinelabs.conductor.ControllerHostedRouter.setBackstack(ControllerHostedRouter.java:107)
       at com.bluelinelabs.conductor.Router.setRoot(Router.java:340)
       at com.example.ui.main.MainMenuController.setController(MainMenuController.java:125)
       at com.example.ui.main.MainMenuController.lambda$cEkOkfZd_WKnetSHdFPg2B6cdWY(MainMenuController.java)
       at com.example.ui.main.-$$Lambda$MainMenuController$cEkOkfZd_WKnetSHdFPg2B6cdWY.onSelect(-.java:2)
       at com.eightbitlab.bottomnavigationbar.BottomNavigationBar$3.onClick(BottomNavigationBar.java:200)
       at android.view.View.performClick(View.java:7357)
       at android.view.View.performClickInternal(View.java:7323)
       at android.view.View.access$3200(View.java:849)
       at android.view.View$PerformClick.run(View.java:27895)
       at android.os.Handler.handleCallback(Handler.java:873)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:216)
       at android.app.ActivityThread.main(ActivityThread.java:7266)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)

Sample code:

@PerController
public class MainMenuViewModel extends BaseViewModel<MainMenuCallback> {

    @Inject
    MainMenuViewModel() {
    }

    @Override
    protected void init(Bundle args) {
        sendTimeZone();
    }

    @SuppressLint("CheckResult")
    private void sendTimeZone() {
        TimeZone tz = TimeZone.getDefault();
        mNetworkHelper.setTimeZone(mPreferencesHelper.getMyPhoneNumber(), tz)
                .compose(RxUtil.applyDefaults(this))
                .subscribe(response -> {
                }, this::silentError);
    }
}
public class MainMenuController extends BaseController implements MainMenuCallback {
    private static final String KEY_POSITION = "MainMenuController.key.pos";
    private static final String KEY_INNER_POSITION = "MainMenuController.key.inner.pos";
    private ControllerMainBinding binding;
    private Router router;

    @Inject
    MainMenuViewModel mViewModel;

    private int currentPosition = -1;

    public MainMenuController(int page) {
        this(new BundleBuilder()
                .putInt(KEY_POSITION, page)
                .build());
    }

    public MainMenuController(int page, int innerPage) {
        this(new BundleBuilder()
                .putInt(KEY_POSITION, page)
                .putInt(KEY_INNER_POSITION, innerPage)
                .build());
    }

    public MainMenuController(Bundle args) {
        super(args);
        setHasOptionsMenu(true);
    }

    @NonNull
    @Override
    protected View onCreateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
        BaseApplication.getComponent().controllerComponent(new ControllerModule(getActivity())).inject(this);
        binding = ControllerMainBinding.inflate(inflater, container, false);
        binding.setViewmodel(mViewModel);
        mViewModel.setCallback(this, getArgs());

        router = getChildRouter(binding.container);

        binding.bottomMenu.addTab(new BottomBarItem(R.drawable.icon_main, R.string.menu_main_title));
        binding.bottomMenu.addTab(new BottomBarItem(R.drawable.icon_detaliz, R.string.menu_my_costs));
        binding.bottomMenu.addTab(new BottomBarItem(R.drawable.icon_offers, R.string.menu_services_title));
        binding.bottomMenu.addTab(new BottomBarItem(R.drawable.icon_club, R.string.club));
        binding.bottomMenu.addTab(new BottomBarItem(R.drawable.icon_help, R.string.help));

        binding.bottomMenu.setOnSelectListener(this::setController);
        binding.bottomMenu.setOnReselectListener(this::setController);
        binding.bottomMenu.selectTabAndTriggerListener(getArgs().getInt(KEY_POSITION), false);

        BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(binding.bottomSheet.bottomSheet);
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);

        KeyboardVisibilityEvent.setEventListener(getActivity(), isOpen -> {
            if (isOpen)
                binding.bottomMenu.setVisibility(View.GONE);
            else
                binding.bottomMenu.setVisibility(View.VISIBLE);
        });

        return binding.getRoot();
    }

    private void setController(int position) {
        Controller page;

        if (currentPosition == position)
            return;

        currentPosition = position;

        switch (position) {
            case Constants.MAIN_TAB:
                page = new TabMainController();
                break;
            case Constants.DETALIZ_TAB:
                page = new TabDetalizController();
                break;
            case Constants.OFFERS_TAB:
                page = new TabOffersController(getArgs().getInt(KEY_INNER_POSITION));
                break;
            case Constants.CLUB_TAB:
                page = new OfferController();
                break;
            case Constants.SETTINGS_TAB:
                page = new TabSettingsController();
                break;
            default:
                page = new TabMainController();
                break;
        }
        router.setRoot(RouterTransaction.with(page));
        getArgs().putInt(KEY_POSITION, position);
    }

    @Override
    protected void onAttach(@NonNull View view) {
        super.onAttach(view);
        mViewModel.onAttach();
    }

    @Override
    protected void onDetach(@NonNull View view) {
        super.onDetach(view);
        mViewModel.onDetach();
//        mTabStateManager.setTab(TabStateManager.Tabs.NONE);
    }

    @Override
    public void showMessage(@NonNull String message, @NonNull int... duration) {
        //https://stackoverflow.com/questions/36332487/move-snackbar-above-the-bottom-bar
        int dur = duration.length > 0 ? duration[0] : Snackbar.LENGTH_SHORT;
        Snackbar snack = Snackbar.make(binding.getRoot(), message, dur);
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)
                snack.getView().getLayoutParams();
        params.setMargins(0, 0, 0, binding.bottomMenu.getHeight());
        snack.getView().setLayoutParams(params);
        snack.show();

//        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showMessage(int message, @NonNull int... duration) {
        int dur = duration.length > 0 ? duration[0] : Snackbar.LENGTH_SHORT;
        Snackbar snack = Snackbar.make(binding.getRoot(), message, dur);
        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)
                snack.getView().getLayoutParams();
        params.setMargins(0, 0, 0, binding.bottomMenu.getHeight());
        snack.getView().setLayoutParams(params);
        snack.show();
//        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
    }

    public BottomSheetBinding getBottomSheetB() {
        return binding.bottomSheet;
    }
}
EricKuck commented 4 years ago

I'm guessing this one isn't easily reproducible?

TikTak123 commented 4 years ago

I think so. I will try to explorer and reproduce this error. If I will get some results, I will notify you immediately.

EricKuck commented 4 years ago

Yeah, please let me know if you figure out some steps to reproduce. I've been banging my head against the wall on this one for quite a while and I'm getting nowhere. Thanks!

TikTak123 commented 4 years ago

Log error without obfuscation code

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.bluelinelabs.conductor.Controller.getChildRouters()' on a null object reference
       at com.bluelinelabs.conductor.ControllerHostedRouter.getSiblingRouters(ControllerHostedRouter.java:240)
       at com.bluelinelabs.conductor.Router.removeAllExceptVisibleAndUnowned(Router.java:882)
       at com.bluelinelabs.conductor.Router.setBackstack(Router.java:409)
       at com.bluelinelabs.conductor.ControllerHostedRouter.setBackstack(ControllerHostedRouter.java:108)
       at com.bluelinelabs.conductor.Router.setRoot(Router.java:337)
       at com.example.ui.main.MainMenuController.setController(MainMenuController.java:122)
       at com.example.ui.main.MainMenuController.lambda$cEkOkfZd_WKnetSHdFPg2B6cdWY()
       at com.example.ui.main.-$$Lambda$MainMenuController$cEkOkfZd_WKnetSHdFPg2B6cdWY.onSelect(:2)
       at com.eightbitlab.bottomnavigationbar.BottomNavigationBar$3.onClick(BottomNavigationBar.java:199)
       at android.view.View.performClick(View.java:6304)
       at android.view.View$PerformClick.run(View.java:24803)
       at android.os.Handler.handleCallback(Handler.java:794)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:176)
       at android.app.ActivityThread.main(ActivityThread.java:6651)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)
EricKuck commented 4 years ago

This should be fixed in the 3.0.0 release. Please feel free to reopen if you still have the issue after updating!

TikTak123 commented 3 years ago

This crash did not occur in version 3.0 stable. But for the latest SNAPSHOT version it happens again. In latest version of my app I enabled minification and obfuscation code.

EricKuck commented 3 years ago

@TikTak123 it looks like there was an error uploading the snapshot, meaning you ended up testing a pre-3.0 build. I've pushed a new snapshot locally now and am looking into why CI silently errored out. Really sorry about that!