4

我有一个 android 应用程序,需要用户使用 facebook 或 twitter 登录。我设法实现了这两种方法并取得了部分成功。facebook 登录是使用来自 facebook 的教程实现的。

至于 twitter 登录,我只是使用了一个按钮来启动执行 webview 登录的 TwitterLoginActivity,如果它成功启动 TwitterHomeActivity,它在碎片方面的实现与 facebook 登录非常相似。

所以这是整个登录实现的细分

FacebookHomeActivity有 3 个片段

  • FacebookSplashFragment(使用 fb 或 twitter 登录的选项)
  • FacebookSelectionFragment(显示应用菜单)
  • FacebookUserSettingsFragmen(注销用户)。

TwitterHomeActivity有 2 个片段

  • TwitterSelectionFragment(显示应用菜单)
  • TwitterUserSettingsFragment(注销用户)

TwitterLoginActivity(包含一个 webview 来通过我的服务器执行身份验证,它将重定向到 twitter 页面进行登录)

问题是,如果您还没有看到它,如果我从 twitter 帐户注销,我必须启动 FacebookHomeActivity 才能看到登录 facebook 或 twitter 的选项。

这样做非常hacky而且很糟糕。所以我想如果我把它全部做成碎片,它可能会解决我的问题。

LoginActivity(所有登录的主机)包含:

  • LoginSelectionFragment(选择使用 facebook 或 twitter 登录)
  • TwitterLoginFragment(通过 webview 登录用户)
  • FacebookSelectionFragment(授权用户并显示菜单)
  • TwitterSelectionFragment(显示菜单)
  • FacebookUserSettingFragment(注销 fb 用户)
  • TwitterUserSettingFragment(注销 Twitter 用户)

通过利用它来显示不同登录状态下的正确片段:

        @Override
protected void onResumeFragments() {
    super.onResumeFragments();

    Session session = Session.getActiveSession();

    if (session != null && session.isOpened()) {
        // if the session is already open,
        // try to show the selection fragment
        getSupportActionBar().show();
        showFragment(FACEBOOKSELECTION, false);
    }

    else if (Globals.loggedIn() && Globals.isTwitterUser()) {
        // otherwise present the splash screen
        // and ask the person to login.
        getSupportActionBar().show();
        showFragment(TWITTERSELECTION, false);

    } 
    else {
        // otherwise present the splash screen
        // and ask the person to login.
        Globals.logout();
        getSupportActionBar().hide();
        showFragment(LOGINSELECTION, false);
    }

}

让所有登录逻辑作为片段存在对我来说似乎很有意义,但它的行为方式并不像我想象的那样工作。相反,它基本上运行每个片段中 onStart() 中的所有内容,所以想象一下弹出很多progressDiaglogs,除此之外什么都没有发生。backstack 也被弄乱了,导致一个片段从未显示出来。要么我实现了这个错误,要么这是解决这个问题的完全错误的方法。

我的问题是:如果这不是解决问题的好方法,那么实现 Facebook 登录和 Twitter 登录的更好方法是什么。

如果上述内容确实有意义并且没有任何问题,那么您认为我做错了什么?

4

1 回答 1

3

在尝试了大约 5 天的新方法之后,例如使用自己的一组 Fragment 将 Facebook 登录身份验证与其自己的 Activity 隔离,这些 Fragment 也未能按应有的方式运行,我阅读了Fragments Documentation,它让我更好地理解了如何片段实际上可以工作并且注定要工作。对于与我面临类似问题的任何人,我强烈建议您先阅读文档。

我使用的 FragmentManager 或者更确切地说 SupportFragmentManager 与 beginTransaction() 方法一起公开了名为replace()的方法,该方法允许您将当前视图中的片段替换为要显示的片段。这是我如何使用它:

  public void replaceFragment(Fragment f, Boolean addToBackStack) {
        if (addToBackStack) {
            getSupportFragmentManager().beginTransaction()
                    .replace(android.R.id.content, f).addToBackStack(null).commit();
        } else {
            getSupportFragmentManager().beginTransaction()
                    .replace(android.R.id.content, f).commit();
        }
    }

addToBackStack 参数用于决定用户是否可以在显示新片段后导航回该片段。

因此,我没有使用 Facebook Android API 示例中显示的 showFragment(),而是将所有 showFragment() 方法替换为 replaceFragment()。

两者之间的区别在于,当您使用 showFragment() 方法预加载主机活动中的所有片段(在我的情况下为 LoginActivity.java)时,会发生所有片段的 onCreate()、onStart()和 onResume() 函数被调用。这种行为很糟糕,因为我的一些片段开始在 onStart() 方法中执行代码,导致所有 progressDialogs 在不应该显示时也显示出来。

通过使用上面显示的 replaceFragment() 方法,我可以仅在需要显示片段时实例化片段,从而可以正常使用生命周期方法(onCreate()、onStart()、onResume() 等)。

用户登录成功后,我只需向用户显示我的菜单并使用以下方法清除后台堆栈:

public void clearBackStack() {
    FragmentManager manager = getSupportFragmentManager();
    // Get the number of entries in the back stack
    int backStackSize = manager.getBackStackEntryCount();
    // Clear the back stack
    for (int i = 0; i < backStackSize; i++) {
        manager.popBackStack();
    }
}

清除后台堆栈的关键区域是用户成功登录后和用户成功注销时。

有了这个,我能够更好地控制片段,因为它们在生命周期方面表现得像活动。

希望这对外面的人有一些帮助。

于 2013-09-23T11:16:19.017 回答