我目前正在开发一款使用Facebook和Google登录的应用。 到目前为止,我使用LoginActivity,当登录成功时启动MainActivity。
我想用片段而不是两个活动来重写它,所以我想要做的是,当MainActivity启动时,如果用户没有登录,则显示LoginFragment,它完全符合我的LoginActivity所做的,但是我缺少的是什么是如何正确退出LoginFragment,并返回到我的主片段,即DashboardFragment。
我已经阅读了很多相关内容,但有很多方法可以做到这一点,我无法弄清楚哪种方法最好。此外,给出的解决方案通常与>>> import asyncio
>>> async def foo(loop, iv):
... await asyncio.sleep(1, loop=loop)
... print(f'done: {iv}')
...
>>> async def await_coro_later(delay, coro, *args, loop=None):
... await asyncio.sleep(delay, loop=loop)
... await coro(*args)
...
>>> def callback_to_coroutine(coro, loop, *args):
... asyncio.ensure_future(coro(*args), loop=loop)
...
>>> loop = asyncio.get_event_loop()
>>> loop.call_later(2, callback_to_coroutine, foo, loop, loop, 'callback_to_coroutine')
<TimerHandle when=1643515.105561161 callback_to_coroutine(<function foo at 0x1032dfe18>, <_UnixSelecto...e debug=False>, <_UnixSelecto...e debug=False>, 'callback_to_coroutine') at <stdin>:1>
>>> loop.run_until_complete(await_coro_later(5, foo, loop, 'coro_later', loop=loop))
done: callback_to_coroutine
done: coro_later
一样,我认为这不是一种正确的做法。
以下是我在MainActivity的onCreate方法中所做的事情
getActivity.onBackPressed()
我在contentLogin中替换了LoginFragment,因为我的另一个FrameLayout内容位于我的BottomNavigationView之上,我希望LoginFragment占用所有可用位置。
我也覆盖了onActivityResult
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
FragmentManager fragmentManager = getFragmentManager();
navigation.setVisibility(View.INVISIBLE);
fragmentManager.beginTransaction()
.replace(R.id.contentLogin, new LoginFragment()).commit();
}
在我的LoginFragment中
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Fragment fragment = getFragmentManager().findFragmentById(R.id.contentLogin);
fragment.onActivityResult(requestCode, resultCode, data);
}
只有Facebook才能保持简单。
更新14.01
我使用以下代码:
MainActivity:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_login, container, false);
callbackManager = CallbackManager.Factory.create();
LoginManager.getInstance().registerCallback(callbackManager,
new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
final String token = loginResult.getAccessToken().getToken();
Toast.makeText(getActivity(), token, Toast.LENGTH_SHORT).show();
}
@Override
public void onCancel() {
Toast.makeText(getActivity(), "Login canceled", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(FacebookException exception) {
Toast.makeText(getActivity(), "Login error", Toast.LENGTH_SHORT).show();
}
});
return view;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
callbackManager.onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
}
LoginFragment:
@Override
public void onBackPressed() {
Fragment fragment = fragmentManager.findFragmentById(R.id.content);
if (fragment instanceof LoginFragment) {
fragmentManager.beginTransaction().replace(R.id.content, new DashboardFragment())
.commit();
navigation.setVisibility(View.VISIBLE);
} else {
super.onBackPressed();
}
}
还有一个主要问题:
当我使用两个活动时,检查Facebook状态是否完美,现在发生的情况是,如果用户已经登录,应用程序将正确显示DashboardFragment,但Facebook登录活动将显示在上方(如果我点击Facebook登录按钮)登录后,应用程序将崩溃。 我正在使用此代码检查登录状态:
@Override
public void onSuccess(LoginResult loginResult) {
final String token = loginResult.getAccessToken().getToken();
final String user = loginResult.getAccessToken().getUserId();
loginStatus.setText("Login Success :\n" + user + "\n" + token);
getActivity().onBackPressed();
}
这是我得到的例外:
if (accessToken != null)
LoginManager.getInstance().logInWithReadPermissions(this,
Collections.singletonList("public_profile"));
else {
navigation.setVisibility(View.GONE);
fragmentManager.beginTransaction().replace(R.id.content, new LoginFragment())
.commit();
}
由于我现在只实施Facebook登录,我猜Google登录会带来更多问题。
答案 0 :(得分:0)
首先创建MainActivity。在activity_main.xml文件中。创建一个framelayout,或者您可以使用merge标签。
声明帧布局的id。喜欢@ + id / fragment_container到您的帧布局。
然后创建您的登录片段。将您的登录片段加载到主活动的framelayout中,如下所示
FragmentTransaction transaction=null;
transaction=getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container,new LoginFragment());
transaction.commit();
然后在onBackPressed方法内的MainActivity.java文件中覆盖onBackPressed,编写此代码并确保在覆盖onBackPressed时删除super.onBackPressed()方法
FragmentManager manager=getSupportFragmentManager();
Fragment current_frag= manager.findFragmentById(R.id.fragment_container);
if(current_frag instanceof SignInFragment)
{
finish();
}
答案 1 :(得分:0)
我会说使用getActivity()。onBackPressed是完全有效的。
您可以在活动中覆盖它的实现并检查当前的片段数(在Backstack中)。当然你应该维护你的backstack(比如在移动到DashboardFragment后删除LoginFragment)。
我建议不要使用活动结果来降低复杂性。为什么不启动请求&gt;&gt; onSucess,显示下一个片段;否则显示错误。如果用户打开应用程序,应用程序应根据给定值和会话(有效/可更新?)确定是否需要显示LoginActivity。
我没有在任何项目中使用Facebook / Google登录,但我希望这个一般建议有助于为您的问题找到解决方案。
根据评论更新:(14-01-2018)
您的onBackPressed实现可能如此。
@Override
public void onBackPressed() {
int count = getSupportFragmentManager().getBackStackEntryCount();
if(count == 0) {
finish();
} else {
super.onBackPressed();
}
}
如果您的应用的后台堆栈为空,此部分将关闭您的应用。
关于LoginFragment:FragmentTransaction有不同的方法,如addToBackStack。通常,如果要将下一个片段添加到后端堆栈,则应调用该方法。在您的示例中,您应该避免使用LoginFragment。
LoginManager.getInstance().registerCallback(callbackManager,
new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
final String token = loginResult.getAccessToken().getToken();
Toast.makeText(getActivity(), token, Toast.LENGTH_SHORT).show();
}
@Override
public void onCancel() {
Toast.makeText(getActivity(), "Login canceled", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(FacebookException exception) {
Toast.makeText(getActivity(), "Login error", Toast.LENGTH_SHORT).show();
}
});
那部分看起来并不需要使用onActivityResult,你确定吗?您可以在调用onSuccess时执行新的FragmentTransaction。
您可以像这样开始下一个片段(请记住,您需要替换R.id.fragment_container):
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, new DashboardFragment());
transaction.addToBackStack(null);
transaction.commit();