Android Kotlin开发:如何实现全局可访问的AccessToken存储?
Android中全局管理Access Token的正确方案
一、自定义Application类(简单但需配合持久化)
你可以创建自定义Application子类存储token作为全局变量,但要注意进程重启后变量会丢失,所以必须配合持久化存储使用:
class MyApp : Application() { var accessToken: String? = null override fun onCreate() { super.onCreate() // 启动时从持久化存储恢复token accessToken = getSharedPreferences("app_prefs", MODE_PRIVATE) .getString("access_token", null) } // 保存token时同时持久化 fun saveAccessToken(token: String) { accessToken = token getSharedPreferences("app_prefs", MODE_PRIVATE) .edit() .putString("access_token", token) .apply() } }
在Activity中调用:
val token = (application as MyApp).accessToken
注意:记得在AndroidManifest.xml的<application>标签里指定android:name=".MyApp"。
二、封装持久化存储类(推荐,可靠)
直接将token存入SharedPreferences或Jetpack DataStore,封装成单例类供全局调用,这是最稳妥的方案——数据不会因进程重启丢失。
方案1:SharedPreferences单例封装
object TokenManager { private const val PREF_NAME = "token_prefs" private const val KEY_ACCESS_TOKEN = "access_token" fun saveAccessToken(context: Context, token: String) { context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .edit() .putString(KEY_ACCESS_TOKEN, token) .apply() } fun getAccessToken(context: Context): String? { return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .getString(KEY_ACCESS_TOKEN, null) } fun clearAccessToken(context: Context) { context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .edit() .remove(KEY_ACCESS_TOKEN) .apply() } }
使用示例:
// 登录后保存token TokenManager.saveAccessToken(this, "your_token_here") // 其他Activity获取token val token = TokenManager.getAccessToken(this)
方案2:Jetpack DataStore(现代方案,支持协程)
如果项目使用协程,推荐用DataStore替代SharedPreferences,它的线程安全性和可靠性更好:
class TokenManager(private val context: Context) { private val dataStore = context.createDataStore(name = "token_prefs") suspend fun saveAccessToken(token: String) { dataStore.edit { preferences -> preferences[PreferencesKeys.ACCESS_TOKEN] = token } } val accessTokenFlow: Flow<String?> = dataStore.data .map { preferences -> preferences[PreferencesKeys.ACCESS_TOKEN] } private object PreferencesKeys { val ACCESS_TOKEN = stringPreferencesKey("access_token") } } // 封装成单例避免重复创建 object TokenProvider { private var instance: TokenManager? = null fun getInstance(context: Context): TokenManager { return instance ?: synchronized(this) { val newInstance = TokenManager(context.applicationContext) instance = newInstance newInstance } } }
使用示例(需在协程中调用):
// 保存token lifecycleScope.launch { TokenProvider.getInstance(this@LoginActivity).saveAccessToken("your_token") } // 获取token并监听变化 lifecycleScope.launch { TokenProvider.getInstance(this@HomeActivity).accessTokenFlow.collect { token -> // 使用token调用API } }
三、依赖注入(适合中大型项目)
如果是中大型项目,推荐用Hilt这类依赖注入框架,将TokenManager注入到需要的Activity、ViewModel或Repository中,避免到处传递Context:
- 配置Hilt后,创建TokenManager类:
class TokenManager @Inject constructor( @ApplicationContext private val context: Context ) { // 这里可复用上面的SharedPreferences或DataStore实现逻辑 }
- 在Activity中注入并使用:
@AndroidEntryPoint class HomeActivity : AppCompatActivity() { @Inject lateinit var tokenManager: TokenManager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val token = tokenManager.getAccessToken(context) // 使用token调用API } }
不推荐直接用静态类/全局变量的原因
直接用静态变量存token虽然简单,但进程被系统回收后变量会清空,导致后续API调用失败;若处理不当还可能引发内存泄漏(比如持有Context引用)。所以一定要配合持久化存储,或直接采用持久化方案。
内容的提问来源于stack exchange,提问作者Gleb
相关产品推荐
相关产品推荐

