当我尝试使用首选项(数据存储)保存令牌时,应用程序闪烁

问题描述 投票:0回答:1

我这里有一个问题,问题是应用程序闪烁,当我尝试从 API 保存登录令牌时发生这种情况,我正在使用 dataStore 首选项来获取和设置令牌。在我将首选项添加到我的 WelcomeActivity 之前,应用程序运行顺利,但是当我添加获取和设置令牌的功能时,应用程序为空白,我无法触摸 editText,当我关闭并再次打开应用程序时,它会闪烁/闪烁,而不会闪烁停下来,也许你可以帮我找到解决这个问题的解决方案

谢谢你

您可以在此视频中查看错误的详细信息:https://youtu.be/pGTfE29KzO0

这是我的代码

欢迎活动.kt :


import android.content.ContentValues.TAG
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.widget.ViewPager2
import com.example.dicodingsocialmedia.databinding.ActivityWelcomeBinding
import com.example.sosmeddicoding.data.model.ErrorResponse
import com.example.sosmeddicoding.data.model.ResponseLogin
import com.example.sosmeddicoding.data.repo.AuthRepo
import com.example.sosmeddicoding.data.service.ApiConfig
import com.example.sosmeddicoding.ui.auth.RegisterActivity
import com.example.sosmeddicoding.ui.auth.RegisterViewModel
import com.example.sosmeddicoding.ui.auth.RegisterViewModelFactory
import com.example.sosmeddicoding.utils.AuthPreferences
import com.example.sosmeddicoding.utils.CustomEditText
import com.example.sosmeddicoding.utils.dataStore
import com.google.android.material.tabs.TabLayout
import com.google.gson.Gson
import kotlinx.coroutines.launch
import retrofit2.Call
import retrofit2.Callback
import retrofit2.HttpException
import retrofit2.Response

class WelcomeActivity : AppCompatActivity() {
    private lateinit var binding: ActivityWelcomeBinding
    private lateinit var tabLayout: TabLayout
    private lateinit var viewPager2: ViewPager2
    private lateinit var authButton: Button
    private lateinit var editText: CustomEditText

    private lateinit var viewModel: WelcomeViewModel
    private lateinit var authPreferences: AuthPreferences

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityWelcomeBinding.inflate(layoutInflater)
        setContentView(binding.root)

        authButton = binding.buttonLogin
        editText = binding.password

        setMyButtonEnable()

        // Check Token
        authPreferences = AuthPreferences.getInstance(application.dataStore)
        lifecycleScope.launch {
            authPreferences.getAuthToken.collect { savedToken ->
                if (savedToken != "") {
                    startActivity(Intent(applicationContext, MainActivity::class.java))
                } else {
                    startActivity(Intent(applicationContext, WelcomeActivity::class.java))
                }
            }
        }

        editText.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
            }

            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                if (s.toString().length < 8) {
                    editText.error = "Password tidak boleh kurang dari 8 karakter"
                } else {
                    editText.error = null
                }
                setMyButtonEnable()
            }

            override fun afterTextChanged(s: Editable) {
            }
        })
        authButton.setOnClickListener {
            Toast.makeText(
                this@WelcomeActivity,
                editText.text,
                Toast.LENGTH_SHORT
            ).show()
        }


        binding.registerHere.setOnClickListener {
            startActivity(Intent(applicationContext, RegisterActivity::class.java))
        }



        authButton.setOnClickListener {
            showLoading(true)
            val email = binding.email.text.toString()
            val password = binding.password.text.toString()

            val authService = ApiConfig.getApiService()
            val authRepo = AuthRepo(authService)
            viewModel = ViewModelProvider(
                this,
                WelcomeViewModelFactory(authRepo)
            ).get(WelcomeViewModel::class.java)

            lifecycleScope.launch {
                try {
                    val successLogin = viewModel.loginVM(email, password)
                    if (successLogin.error == false && successLogin.loginResult != null) {
                        startActivity(Intent(applicationContext, MainActivity::class.java))
                        val token = successLogin.loginResult.token
                        authPreferences.saveToken(token!!)
                    }
                } catch (e: HttpException) {
                    showLoading(false)
                    val jsonInString = e.response()?.errorBody()?.string()
                    val errorBody = Gson().fromJson(jsonInString, ErrorResponse::class.java)
                    val errorMessage = errorBody.message
                    if (errorMessage != null) {
                        showToast(errorMessage)
                        Toast.makeText(
                            this@WelcomeActivity,
                            "Register Failed, please register again",
                            Toast.LENGTH_LONG
                        ).show()
                    }
                }
            }

        }


    }

    private fun showLoading(isLoading: Boolean) {
        if (isLoading) {
            binding.cardView.visibility = View.VISIBLE
        } else {
            binding.cardView.visibility = View.GONE
        }
    }

    private fun showToast(message: String) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
    }


    private fun setMyButtonEnable() {
        val result = editText.text
        authButton.isEnabled = result != null && result.toString().isNotEmpty()
    }


}

AuthPreferences.kt

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.preferencesDataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

val Context.dataStore : DataStore<Preferences> by preferencesDataStore(name = "auth_token")

class AuthPreferences private constructor(private val dataStore: DataStore<Preferences>) {

    private val AUTH_TOKEN_KEY = stringPreferencesKey("token")

    val getAuthToken: Flow<String?> = dataStore.data.map { preferences ->
        preferences[AUTH_TOKEN_KEY] ?: ""
    }

    suspend fun saveToken(token: String) {
        dataStore.edit { auth ->
            auth[AUTH_TOKEN_KEY] = token
        }
    }

    companion object {
        @Volatile
        private var INSTANCE: AuthPreferences? = null

        fun getInstance(dataStore: DataStore<Preferences>): AuthPreferences {
            return INSTANCE ?: synchronized(this) {
                val instance = AuthPreferences(dataStore)
                INSTANCE = instance
                instance
            }
        }
    }
}

响应登录.kt:

import kotlinx.parcelize.Parcelize
import android.os.Parcelable
import com.google.gson.annotations.SerializedName

@Parcelize
data class ResponseLogin(

    @field:SerializedName("loginResult")
    val loginResult: LoginResult? = null,

    @field:SerializedName("error")
    val error: Boolean? = null,

    @field:SerializedName("message")
    val message: String? = null
) : Parcelable

@Parcelize
data class LoginResult(

    @field:SerializedName("name")
    val name: String? = null,

    @field:SerializedName("userId")
    val userId: String? = null,

    @field:SerializedName("token")
    val token: String? = null
) : Parcelable

这是我的 logcat :

kotlin authentication token android-preferences datastore
1个回答
0
投票

WelcomeActivity.onCreate
中启动一个协程时,您创建了一个循环,该协程启动了一个启动协程的活动,依此类推。

© www.soinside.com 2019 - 2024. All rights reserved.