Dar*_*een 23 android android-fragments kotlin
我registerForActivityResult在我的开发中使用 谷歌登录实现。一切正常,直到我将片段依赖项升级到 1.3.0-beta01。应用程序当前崩溃并出现错误java.lang.IllegalStateException: LifecycleOwner SignupChoicesFragment{8e0e269} (193105b9-afe2-4941-a368-266dbc433258) id=0x7f090139} is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.
我在 oncreate 之前使用了延迟加载的函数,但它仍然无法工作。
class SignupChoicesFragment : DaggerFragment() {
@Inject
lateinit var viewModelProviderFactory: ViewModelFactory
val userViewModel: UserViewModel by lazy {
ViewModelProvider(this, viewModelProviderFactory).get(UserViewModel::class.java)
}
@Inject
lateinit var mGoogleSignInClient:GoogleSignInClient
val arg:SignupChoicesFragmentArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_signup_choices, container, false)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
google_sign_in_button.setOnClickListener {
val intent = mGoogleSignInClient.signInIntent
val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult(), ActivityResultCallback {result->
if (result.resultCode == Activity.RESULT_OK) {
val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
task.addOnCompleteListener {
if (it.isSuccessful) {
val account: GoogleSignInAccount? =
it.getResult(ApiException::class.java)
val idToken = it.result?.idToken
val email = account?.email
val lastName = account?.familyName
val firstName = account?.givenName
val otherName = account?.displayName
val imageUrl = account?.photoUrl
val category = arg.category
val newUser = User()
newUser.firstName = firstName
newUser.lastName = lastName
newUser.otherName = otherName
newUser.category = category
newUser.email = email
newUser.imageUrl = imageUrl.toString()
userViewModel.currentUser = newUser
newUser.token = idToken
i(title, "idToken $idToken")
requireActivity().gdToast("Authentication successful", Gravity.BOTTOM)
val action = SignupChoicesFragmentDirections.actionSignupChoicesFragmentToEmailSignupFragment()
action.newUser = newUser
goto(action)
} else {
requireActivity().gdToast(
"Authentication Unsuccessful",
Gravity.BOTTOM
)
Log.i(title, "Task not successful")
}
}
} else {
Log.i(title, "OKCODE ${Activity.RESULT_OK} RESULTCODE ${result.resultCode}")
}
}).launch(intent)
}
}
Run Code Online (Sandbox Code Playgroud)
Moh*_*laa 19
从文档中引用
在创建片段或活动之前调用 registerForActivityResult() 是安全的,允许在为返回的 ActivityResultLauncher 实例声明成员变量时直接使用它。 注意:虽然在创建片段或活动之前调用 registerForActivityResult() 是安全的,但在片段或活动的生命周期达到 CREATED 之前,您无法启动 ActivityResultLauncher。
因此解决您的问题,您的移动电话登记外onCreate(),并把它fragment的范围,并在google_sign_in_buttonclick-listener呼叫发射功能
注意:如果您使用的是Kotlin-Android-Extention,请将您的click-listener电话转至onViewCreated()
您必须val launcher = registerForActivityResult...从 中删除setOnClickListener,然后将其保存在变量中,在您的示例中是 is launcher,并在setOnClickListener使用 .launch 执行变量中,在您的示例中 es launcher。
你的代码看起来像这样
google_sign_in_button.setOnClickListener {
val intent = mGoogleSignInClient.signInIntent
launcher.launch(intent)
}
private val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult(), ActivityResultCallback {result->
if (result.resultCode == Activity.RESULT_OK) {
val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
task.addOnCompleteListener {
if (it.isSuccessful) {
val account: GoogleSignInAccount? =
it.getResult(ApiException::class.java)
val idToken = it.result?.idToken
val email = account?.email
val lastName = account?.familyName
val firstName = account?.givenName
val otherName = account?.displayName
val imageUrl = account?.photoUrl
val category = arg.category
val newUser = User()
newUser.firstName = firstName
newUser.lastName = lastName
newUser.otherName = otherName
newUser.category = category
newUser.email = email
newUser.imageUrl = imageUrl.toString()
userViewModel.currentUser = newUser
newUser.token = idToken
i(title, "idToken $idToken")
requireActivity().gdToast("Authentication successful", Gravity.BOTTOM)
val action = SignupChoicesFragmentDirections.actionSignupChoicesFragmentToEmailSignupFragment()
action.newUser = newUser
goto(action)
} else {
requireActivity().gdToast(
"Authentication Unsuccessful",
Gravity.BOTTOM
)
Log.i(title, "Task not successful")
}
}
} else {
Log.i(title, "OKCODE ${Activity.RESULT_OK} RESULTCODE ${result.resultCode}")
}
})
Run Code Online (Sandbox Code Playgroud)
来源:https ://medium.com/codex/android-runtime-permissions-using-registerforactivityresult-68c4eb3c0b61
小智 7
如果您使用的是 Fragment,请确保您没有registerForActivityResult在活动上执行。Fragments 也有一个registerForActivityResult,这就是你应该使用的。
我找到了一个可以在任何地方使用的解决方案。
查看ActivityResultRegistry源代码,您可以看到有两个register函数,并且只有一个抛出if lifecycle.getCurrentState().isAtLeast(Lifecycle.State.STARTED)。另一个不关心生命周期,但你必须调用unregister自己。
调用此方法时,当不再需要启动器释放可能在注册回调中捕获的任何值时,您必须对返回的 ActivityResultLauncher 调用 ActivityResultLauncher.unregister() 。
这是我想出的扩展函数:
fun <I, O> ComponentActivity.registerActivityResultLauncher(
contract: ActivityResultContract<I, O>,
callback: ActivityResultCallback<O>
): ActivityResultLauncher<I> {
val key = UUID.randomUUID().toString()
return activityResultRegistry.register(key, contract, callback)
}
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
val launcher = activity.registerActivityResultLauncher(
contract = ActivityResultContracts.StartActivityForResult(),
callback = { result ->
//do something with the result
}
)
Run Code Online (Sandbox Code Playgroud)
完成后不要忘记取消注册:
launcher.unregister()
Run Code Online (Sandbox Code Playgroud)
详细信息:在单独的班级中接收活动结果
在创建片段或活动之前可以安全地调用 registerForActivityResult() ,从而允许在为返回的 ActivityResultLauncher 实例声明成员变量时直接使用它。
您应该在创建视图之前调用registerForActivityResult。成员变量或 onCreate()
小智 5
对我来说,问题是我正在调用registerForActivityResult一个onClickListener,它只在单击按钮时调用(此时应用程序处于 RESUMED 状态)。将调用移到按钮之外onClickListener并进入 Activity 的onCreate方法修复了它。
| 归档时间: |
|
| 查看次数: |
8920 次 |
| 最近记录: |