我有3个屏幕的工作流程。从“屏幕1”到访问“屏幕2”,用户必须接受我在我的图片“模态”中调用的某种条款和条件。但他只需要接受这些条件一次。下次他在第一个屏幕上时,他可以直接进入屏幕2.用户可以选择不接受这些条款,因此我们返回“屏幕1”并且不要尝试转到“屏幕2”。
我想知道如何使用新的navigation component。
以前,我会做什么:
startActivityForResult()
并等待模态的结果。将条款标记为已接受。启动“屏幕2”但是使用导航图,无法启动片段来获得结果。
我可以在“模态”屏幕上标记接受的条款,然后从那里开始“屏幕2”。问题是,要访问屏幕2,我需要做一个网络请求。我不想复制对API的调用并在“屏幕1”和“模态”中处理其结果。
有没有办法使用Jetpack导航从“模态”返回到“屏幕1”并提供一些信息(用户接受条款)?
编辑:我目前通过使用Yahya建议的相同流程绕过它:使用仅适用于模态的活动并使用“屏幕1”中的startActivityForResult
。我只是想知道我是否可以继续使用导航图进行整个流程。
答案 0 :(得分:14)
最近(在androidx-navigation-2.3.0-alpha02中),Google发布了一种使用片段实现此行为的正确方法。
简而言之:(摘自发行说明)
如果Fragment A
需要来自Fragment B
的结果。
A
应该从 currentBackStackEntry 中获取savedStateHandle,调用getLiveData提供密钥并观察结果。
findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<Type>("key")?.observe(
viewLifecycleOwner) {result ->
// Do something with the result.
}
B
应该从 previousBackStackEntry 中获取savedStateHandle,并使用与A
findNavController().previousBackStackEntry?.savedStateHandle?.set("key", result)
答案 1 :(得分:10)
在AndroidX Fragment库的1.3.0-alpha04版中,他们引入了新的API,这些API允许在import Component from "./Component.js"
s之间传递数据。
添加了对通过FragmentManager上的新API在两个Fragment之间传递结果的支持。这适用于层次结构片段(父/子),DialogFragments和Navigation中的片段,并确保仅在至少STARTED时才将结果发送到您的Fragment。 (b/149787344)
Cannot find module 'next/link'
获得了两种新方法:
FragmentManager#setFragmentResult(String, Bundle)
,您可以像对待现有的Activity#setResult
一样; FragmentManager#setFragmentResultListener(String, LifecycleOwner, FragmentResultListener)
,可让您收听/观察结果更改。如何使用它?
在Fragment
中,通过FragmentManager
方法将FragmentA
添加到FragmentResultListener
:
FragmentManager
在onCreate
中添加以下代码以返回结果:
setFragmentResultListener("request_key") { requestKey: String, bundle: Bundle ->
val result = bundle.getString("your_data_key")
// do something with the result
}
例如,使用以下命令开始FragmentB
:
val result = Bundle().apply {
putString("your_data_key", "Hello!")
}
setFragmentResult("request_key", result)
关闭/完成FragmentB
通话:
findNavController().navigate(NavGraphDirections.yourActionToFragmentB())
现在,您的FragmentB
应该会收到通知,您应该会收到结果。
(我正在使用findNavController().navigateUp()
来简化上面的代码)
答案 2 :(得分:5)
现在导航组件中似乎没有startActivityForResult
的等效项。但是,如果您使用LiveData和ViewModel,您可能会对this article感兴趣。作者正在使用活动范围的ViewModel和LiveData来实现片段。
答案 3 :(得分:2)
共享视图模型有两种选择。
有趣的navigationBackWithResult(结果:捆绑包),如此处https://medium.com/google-developer-experts/using-navigation-architecture-component-in-a-large-banking-app-ac84936a42c2
创建回调。
ResultCallback.kt
ubox18@ubox18:~/ng-apps$ ng new techadda
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS
CREATE techadda/README.md (1025 bytes)
CREATE techadda/.editorconfig (246 bytes)
CREATE techadda/.gitignore (629 bytes)
CREATE techadda/angular.json (3825 bytes)
CREATE techadda/package.json (1307 bytes)
CREATE techadda/tsconfig.json (435 bytes)
CREATE techadda/tslint.json (1621 bytes)
CREATE techadda/src/favicon.ico (5430 bytes)
CREATE techadda/src/index.html (295 bytes)
CREATE techadda/src/main.ts (372 bytes)
CREATE techadda/src/polyfills.ts (2841 bytes)
CREATE techadda/src/styles.css (80 bytes)
CREATE techadda/src/test.ts (642 bytes)
CREATE techadda/src/browserslist (388 bytes)
CREATE techadda/src/karma.conf.js (1021 bytes)
CREATE techadda/src/tsconfig.app.json (166 bytes)
CREATE techadda/src/tsconfig.spec.json (256 bytes)
CREATE techadda/src/tslint.json (244 bytes)
CREATE techadda/src/assets/.gitkeep (0 bytes)
CREATE techadda/src/environments/environment.prod.ts (51 bytes)
CREATE techadda/src/environments/environment.ts (662 bytes)
CREATE techadda/src/app/app-routing.module.ts (245 bytes)
CREATE techadda/src/app/app.module.ts (393 bytes)
CREATE techadda/src/app/app.component.css (0 bytes)
CREATE techadda/src/app/app.component.html (1152 bytes)
CREATE techadda/src/app/app.component.spec.ts (1101 bytes)
CREATE techadda/src/app/app.component.ts (212 bytes)
CREATE techadda/e2e/protractor.conf.js (752 bytes)
CREATE techadda/e2e/tsconfig.e2e.json (213 bytes)
CREATE techadda/e2e/src/app.e2e-spec.ts (637 bytes)
CREATE techadda/e2e/src/app.po.ts (251 bytes)
Unhandled rejection Error: EACCES: permission denied, open '/home/ubox18/.npm/_cacache/tmp/713bc9a4'
Unhandled rejection Error: EACCES: permission denied, open '/home/ubox18/.npm/_cacache/tmp/587a6d34'
Unhandled rejection Error: EACCES: permission denied, open '/home/ubox18/.npm/_cacache/tmp/d24ecd3c'
Unhandled rejection Error: EACCES: permission denied, open '/home/ubox18/.npm/_cacache/tmp/183be234'
Unhandled rejection Error: EACCES: permission denied, open '/home/ubox18/.npm/_cacache/tmp/65378392'
Unhandled rejection Error: EACCES: permission denied, open '/home/ubox18/.npm/_cacache/tmp/c2e18bc1'
Unhandled rejection Error: EACCES: permission denied, open '/home/ubox18/.npm/_cacache/tmp/19e9a26f'
Unhandled rejection Error: EACCES: permission denied, open '/home/ubox18/.npm/_cacache/tmp/14846b9a'
Unhandled rejection Error: EACCES: permission denied, open '/home/ubox18/.npm/_cacache/tmp/1d1b4940'
Unhandled rejection Error: EACCES: permission denied, open '/home/ubox18/.npm/_cacache/tmp/fb3fc3bb'
npm ERR! cb() never called!
npm ERR! This is an error with npm itself. Please report this error at:
npm ERR! <https://npm.community>
Package install failed, see above.
将此回调作为参数传递(请注意,它必须实现Serializable,并且接口需要在其自己的文件中声明。)
interface ResultCallback : Serializable {
fun setResult(result: Result)
}
使framgent A实现ResultCallback,片段B by将获取参数并将数据通过args.callback.setResult(x)传递回
答案 4 :(得分:0)
还有另一种替代方法。您可以使用从模式返回到screen1的另一种导航操作,而不是使用popBackStack()
。通过该操作,您可以发送任何您想要筛选的数据。使用此策略来确保模式屏幕不会再留在导航后退堆栈中:https://stackoverflow.com/a/54015319/4672107。
我看到的这种策略的唯一问题是,按下后退按钮不会发送任何数据,但是大多数用例需要在特定的用户操作之后进行导航,并且在这种情况下,此解决方法将起作用。
答案 5 :(得分:0)
要获取调用者片段,请使用类似fragmentManager.putFragment(args, TargetFragment.EXTRA_CALLER, this)
的内容,然后在目标片段中使用
if (args.containsKey(EXTRA_CALLER)) {
caller = fragmentManager?.getFragment(args, EXTRA_CALLER)
if (caller != null) {
if (caller is ResultCallback) {
this.callback = caller
}
}
}