为什么这个java递归方法没有创建无限循环?

时间:2017-08-20 10:57:08

标签: java android

我是Android开发的新手,在尝试阅读代码示例时,我遇到了一个从内部调用的方法,所以逻辑上它应该创建一个无限循环来调用自身。但事实并非如此。为什么呢?

在我的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?
            }
        });
    }

并称之为:

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

修改

以下是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());
        }
    }

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

4 个答案:

答案 0 :(得分:2)

onWishlistSelected 调用自身,因此这里没有无限递归。

它正在调用launchUserSpecificFragment,它接收一个实现LoginDialogInterface作为参数的匿名类的实例。

匿名类包含调用successfulLoginOrRegistration的{​​{1}}方法,但调用onWishlistSelected并不一定会执行onWishlistSelected方法。执行successfulLoginOrRegistration时取决于successfulLoginOrRegistration

的逻辑

答案 1 :(得分:1)

请注意,您调用onWishlistSelected的地方位于匿名类内,而不是直接位于onWishlistSelected方法本身。

如果仔细观察,您对onWishlistSelected的调用会被放入名为successfulLoginOrRegistration的方法中。这意味着只有在调用successfulLoginOrRegistration时,才会调用onWishlistSelected

那么什么时候会调用successfulLoginOrRegistration?我从你给出的代码数量中无法知道这一点。

现在让我们假设successfulLoginOrRegistration被调用。因此,系统会调用onWishlistSelected,但只会在下次调用onWishlistSelected时调用successfulLoginOrRegistration

现在您可能会问,"堆栈跟踪是否会被这两个方法调用填充?"答案可能不是。 onWishlistSelected可能会先返回,以便代码的其他部分能够调用successfulLoginOrRegistration。因此堆栈跟踪不会溢出。

我将使用一个更容易理解的例子来说明这一点:

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

这不会创建无限循环。 someMethod仅在用户按下按钮时执行。当用户按下按钮时,actionPerformed被调用,someMethod也被调用。但是在用户再次点击按钮之前没有任何反应。

答案 2 :(得分:0)

此方法永远不会无限调用因为有successfulLoginOrRegistration接口正在执行您的onWishlistSelected方法。简而言之,只有当onWishlistSelected在[{1}}中获得回调时,您的interface方法才会执行。

答案 3 :(得分:0)

onWishListSelected方法不会调用自身。它定义了一个SuccessfulLoginOrRegistration方法,但从不调用它。我相信这就是你想要的。

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