android - 为什么通过 SupportFragmentManager 添加 fragment 的顺序很重要?

标签 android facebook android-fragments facebook-android-sdk

我正在创建一个 AuthenticationActivity,它将为用户提供通过 Facebook、Twitter 或应用特定身份验证登录的选项。遵循写得好的tutorial Use Facebook Login from the Facebook Android SDK documentation我有 Facebook 身份验证工作。

不幸的是,当我继续添加 Twitter fragment 以提供类似的登录功能时,我遇到了问题。突然,Facebook 登录按钮不会改变状态,我对 Facebook 的身份验证也不会完全完成,尽管我可以看到身份验证回调被返回。

兜兜转转后,我最终决定更改AuthenticationActivity 通过SupportFragmentManager 添加 fragment 的顺序。当我这样做时,Facebook 又开始工作了,但随后 Twitter fragment 就崩溃了。

getSupportFragmentManager()
    .beginTransaction()
    .add(android.R.id.content, twitterFragment)
    .add(android.R.id.content, facebookFragment)
    .commit();

这并没有让我感觉更好,而是让我感觉更糟。我承认不完全理解 fragment ,但我完全不明白为什么添加 fragment 的顺序会产生这种影响。哪个先到是行不通的,但后加的那个行。重要的是要注意我正在使用 及其 fragment 实现。

下面你会找到我的 Activity 和 fragment 代码

AuthenticationActivity

public class AuthenticationActivity extends SherlockFragmentActivity {

    private FacebookFragment facebookFragment;
    private TwitterFragment twitterFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState == null) {
            addFragments();
        } else {
            restoreFragments();
        }
    }

    private void addFragments() {
        facebookFragment = new FacebookFragment();
        twitterFragment = new TwitterFragment();

        // TODO the order of this MATTERS if Facebook isn't last
        // Facebook auth breaks and vice versa.
        getSupportFragmentManager()
            .beginTransaction()
            .add(android.R.id.content, twitterFragment)
            .add(android.R.id.content, facebookFragment)
            .commit();
    }

    private void restoreFragments() {
        facebookFragment = (FacebookFragment) getSupportFragmentManager()
            .findFragmentById(android.R.id.content);
        twitterFragment = (TwitterFragment) getSupportFragmentManager()
            .findFragmentById(android.R.id.content);
    }
}

Facebook fragment (主要基于 SDK documentation example )

public class FacebookFragment extends SherlockFragment {

    private UiLifecycleHelper uiHelper;
    private static final String TAG = FacebookFragment.class.getSimpleName();

    private Session.StatusCallback callback = new Session.StatusCallback() {
        @Override
        public void call(Session session, SessionState state,
            Exception exception) {
            onSessionStateChange(session, state, exception);
        }
    };

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.authentication, container, false);

        LoginButton facebookButton
            = (LoginButton) view.findViewById(R.id.facebookButton);
        facebookButton.setFragment(this);

        return view;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        uiHelper = new UiLifecycleHelper(getActivity(), callback);
        uiHelper.onCreate(savedInstanceState);
    }

    @Override
    public void onResume() {
        super.onResume();

        Session session = Session.getActiveSession();
        if (session != null && (session.isOpened() || session.isClosed())) {
            onSessionStateChange(session, session.getState(), null);
        }

        uiHelper.onResume();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        uiHelper.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onPause() {
        super.onPause();
        uiHelper.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        uiHelper.onDestroy();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        uiHelper.onSaveInstanceState(outState);
    }

    private void onSessionStateChange(Session session, SessionState state,
        Exception exception) {
        if (state.isOpened()) {
            Log.i(TAG, "Logged in...");
        } else if (state.isClosed()) {
            Log.i(TAG, "Logged out...");
        } else {
            Log.i(TAG, "unknown state " + state);
        }
    }
}

推特 fragment

public class TwitterFragment extends SherlockFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.authentication, container, false);

        Button twitterButton = (Button) view.findViewById(R.id.twitterButton);
        twitterButton.setOnClickListener(twitterClickListener);

        return view;
    }

    private OnClickListener twitterClickListener = new OnClickListener() {
        public void onClick(View v) {
            Context context = v.getContext();

            Intent intent = new Intent(context, TwitterLoginActivity.class);
            context.startActivity(intent);
        }
    };
}

为什么通过 SupportFragmentManger 添加上述 fragment 的顺序很重要?

最佳答案

 private void restoreFragments() {
        facebookFragment = (FacebookFragment) getSupportFragmentManager()
            .findFragmentById(android.R.id.content);
        twitterFragment = (TwitterFragment) getSupportFragmentManager()
            .findFragmentById(android.R.id.content);
    }

您需要为每个 fragment 分配一个不同的 ID,否则对于给定的 ID,您将始终获得相同的 fragment 。我猜你会得到第一个声明/添加的 fragment ,但这取决于实现。 (您可能遇到了类转换异常)。

要解决此问题,请为它们分配不同的 ID 并将它们添加到不同的占位符。

.beginTransaction()
            .add(R.id.twitter_fragment, twitterFragment)
            .add(R.id.facebook_fragment, facebookFragment)
            .commit();

这还需要进行其他更改,但希望您能做到。

关于android - 为什么通过 SupportFragmentManager 添加 fragment 的顺序很重要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15354350/

相关文章:

android - 是否可以将类的内部类注册为广播接收器

android - 在选项卡中显示偏好 Activity

Android:下载大文件

android - 如何在Android(2016)中与社交网络(Whatsapp,Facebook)共享音频?

php - 如何使用 Facebook Graph API 为事件上传图片?

html - 在 iframe 或框架中打开 Facebook 页面?

java - 在 fragment 中使用数据库

java lang Nullpointerexception 更新谷歌服务后

android - fragment 中的 ViewPager

android - 嵌套 fragment 在方向更改时创建两次