简体   繁体   中英

Why this java recursive method not creating infinite loop?

I am new to android development, while trying to read a code example, I encountered a method which is being called from within itself, so logically it should create an infinite loop of calling itself. But it does not. why?

In my MainActivity.java

 public void onWishlistSelected() {
        launchUserSpecificFragment(new WishlistFragment(), WishlistFragment.class.getSimpleName(), new LoginDialogInterface() {
            @Override
            public void successfulLoginOrRegistration(User user) {
                // If login was successful launch WishlistFragment.
                onWishlistSelected(); // Why doesn't this create infine loop?
            }
        });
    }

and calling it:

public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        if (id == R.id.action_wish_list) {
            onWishlistSelected();
            return true;
        } else if (id == R.id.action_cart) {
            onCartSelected();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

EDIT

Here is the code inside launchUserSpecificFragment

   private void launchUserSpecificFragment(Fragment fragment, String transactionTag, LoginDialogInterface loginListener) {
        if (SettingsMy.getActiveUser() != null) {
            replaceFragment(fragment, transactionTag);
        } else {
            DialogFragment loginDialogFragment = LoginDialogFragment.newInstance(loginListener);
            loginDialogFragment.show(getSupportFragmentManager(), LoginDialogFragment.class.getSimpleName());
        }
    }

and replaceFragment

 private void replaceFragment(Fragment newFragment, String transactionTag) {
        if (newFragment != null) {
            FragmentManager frgManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = frgManager.beginTransaction();
            fragmentTransaction.setAllowOptimization(false);
            fragmentTransaction.addToBackStack(transactionTag);
            fragmentTransaction.replace(R.id.main_content_frame, newFragment).commit();
            frgManager.executePendingTransactions();
        } else {
            Timber.e(new RuntimeException(), "Replace fragments with null newFragment parameter.");
        }
    }

onWishlistSelected is not calling itself, so there is not infinite recursion here.

It is calling launchUserSpecificFragment , which receives an instance of an anonymous class implementing LoginDialogInterface as an argument.

The anonymous class contains a successfulLoginOrRegistration method that calls onWishlistSelected , but calling onWishlistSelected doesn't necessarily execute that successfulLoginOrRegistration method. When successfulLoginOrRegistration will be executed depends on the logic of launchUserSpecificFragment .

Note that the place where you call onWishlistSelected is inside an anonymous class and not directly in the onWishlistSelected method itself.

If you look closely that your call to onWishlistSelected is put inside a method called successfulLoginOrRegistration . This means that only when successfulLoginOrRegistration is called, onWishlistSelected is called.

So when will successfulLoginOrRegistration be called? I cannot know this from the amount of code you have given.

Now let's suppose that successfulLoginOrRegistration is called. As a result, onWishlistSelected is called, but then onWishlistSelected will only be called the next time successfulLoginOrRegistration is called.

Now you might ask, "Wouldn't the stack trace be filled with these two method calls?" The answer is probably not. onWishlistSelected will probably return first, so that other parts of the code is able to call successfulLoginOrRegistration . So the stack trace won't overflow.

I will use an easier-to-understand example to illustrate this:

private static JButton btn = new JButton("press me");
public static void main(String[]args) throws Exception {
    JFrame frame = new JFrame();
    frame.add(btn);
    someMethod();
    frame.setVisible(true);
}

public static void someMethod() {
    btn.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("button pressed");
            someMethod();
        }
    });
}

This will not create an infinite loop. someMethod only executes when the user presses the button. When the user presses the button, actionPerformed is called and so is someMethod . But then nothing happens, until the user clicks the button again.

This method will never call infinitely reason is there is successfulLoginOrRegistration interface which is executing your onWishlistSelected method. In short your onWishlistSelected method will execute only when your interface will get callback in successfulLoginOrRegistration .

onWishListSelected method is not calling itself. It defines a successfulLoginOrRegistration method but never calls it. This is what you want, I believe.

public void onWishlistSelected() {
        boolean loginSuccess = false; 
        launchUserSpecificFragment(new WishlistFragment(), WishlistFragment.class.getSimpleName(), new LoginDialogInterface() {
            @Override
            public void successfulLoginOrRegistration(User user) {
                // If login was successful launch WishlistFragment.
            }
            // set true when login successfully .
            // loginSuccess = true;
        });
        // call untill successfully logged in.
        if(loginSuccess == false){
          onWishlistSelected();
        }
}

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