You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从AuthWebViewActivity向调用类Auth返回数据?

从AuthWebViewActivity向Auth返回数据的方案

一、实现方式:借助宿主Activity的结果回调

因为Auth本身不是Activity,它持有的Context其实是LoginActivity的实例,所以需要通过LoginActivity的生命周期接收AuthWebViewActivity的返回结果,再把结果传递给Auth处理——这样既能保持AuthWebViewActivity的简洁,又能把所有认证逻辑集中在Auth里。

1. 推荐:使用AndroidX的ActivityResultContracts

这是Google推荐替代旧版startActivityForResult的方案,更安全且具备生命周期感知能力:

步骤1:在LoginActivity中注册结果回调并传给Auth

// LoginActivity.kt
class LoginActivity : AppCompatActivity() {
    private lateinit var auth: Auth

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        // 注册Activity结果回调
        val authResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == RESULT_OK) {
                // 将返回的数据交给Auth处理
                auth.handleAuthResult(result.data)
            }
        }

        // 创建Auth实例时传入回调Launcher
        auth = Auth(this, authResultLauncher)
    }
}

步骤2:修改Auth类,用Launcher启动Activity并处理结果

// Auth.kt
class Auth(
    private val context: Context,
    private val resultLauncher: ActivityResultLauncher<Intent>
) {
    // 对外暴露的启动认证页面方法
    fun startAuthFlow(url: String) {
        val intent = Intent(context, AuthWebViewActivity::class.java)
        intent.putExtra("url", url)
        resultLauncher.launch(intent)
    }

    // 处理AuthWebViewActivity返回的认证数据
    fun handleAuthResult(data: Intent?) {
        val authToken = data?.getStringExtra("auth_token")
        // 这里写所有后续认证逻辑:存token、校验、请求接口等
    }
}

步骤3:在AuthWebViewActivity中返回数据

// AuthWebViewActivity.kt
class AuthWebViewActivity : AppCompatActivity() {
    // 假设WebView加载完成后获取到了认证token
    private fun onAuthCompleted(token: String) {
        val resultIntent = Intent().apply {
            putExtra("auth_token", token)
        }
        setResult(RESULT_OK, resultIntent)
        finish()
    }
}

2. 兼容旧版:使用startActivityForResult

如果项目还在使用旧版API,可采用这种方式:

步骤1:LoginActivity重写onActivityResult并传给Auth

// LoginActivity.kt
class LoginActivity : AppCompatActivity() {
    private lateinit var auth: Auth

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        auth = Auth(this)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == Auth.AUTH_REQUEST_CODE && resultCode == RESULT_OK) {
            auth.handleAuthResult(data)
        }
    }
}

步骤2:Auth类调用startActivityForResult

// Auth.kt
class Auth(private val activity: Activity) {
    companion object {
        const val AUTH_REQUEST_CODE = 1001
    }

    fun startAuthFlow(url: String) {
        val intent = Intent(activity, AuthWebViewActivity::class.java)
        intent.putExtra("url", url)
        activity.startActivityForResult(intent, AUTH_REQUEST_CODE)
    }

    fun handleAuthResult(data: Intent?) {
        // 处理认证结果逻辑
    }
}

二、关于Auth类启动Activity的设计建议

  • 避免内存泄漏:直接持有Activity的强引用容易导致内存泄漏,建议改用WeakReference包裹Activity:
class Auth(private val activityRef: WeakReference<Activity>) {
    fun startAuthFlow(url: String) {
        val activity = activityRef.get() ?: return // 若Activity已销毁则不执行
        val intent = Intent(activity, AuthWebViewActivity::class.java)
        intent.putExtra("url", url)
        activity.startActivityForResult(intent, AUTH_REQUEST_CODE)
    }
}
// LoginActivity中创建实例:auth = Auth(WeakReference(this))
  • 设计合理性:让AuthWebViewActivity只负责WebView展示和结果收集,所有认证逻辑放在Auth中是符合单一职责原则的,这个设计方向没问题。如果Auth需要全局复用,可以考虑设计成单例,但要注意传入的Context必须是Activity类型(启动Activity必须用Activity Context)。

内容的提问来源于stack exchange,提问作者danshat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 19:05:22