在收到任何資料之前,我需要按兩次“登錄按鈕”。我第一次按下按鈕時,我收到資料:“空”。第二次,我收到了登錄所需的資料。問題是:“我怎樣才能通過第一個點擊事件接收我的資料?”
XML:
android:id="@ id/login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="30dp"
android:padding="10dp"
android:text="@string/login_login"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
登錄活動:
private lateinit var listIntent: Intent
class LoginActivity : AppCompatActivity() {
private lateinit var binding: FragmentLoginBinding
private val viewModel: LoginViewModel by viewModels()
private val EMAIL_ADDRESS_PATTERN = Pattern.compile(
"[a-zA-Z0-9\\ \\.\\_\\%\\-\\ ]{1,256}"
"\\@"
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}"
"("
"\\."
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}"
") "
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
try {
this.supportActionBar!!.hide()
} catch (e: NullPointerException) {
}
binding = FragmentLoginBinding.inflate(layoutInflater)
setContentView(binding.root)
**binding.loginButton.setOnClickListener() { launchMain() }**
binding.loginTextNewHereRegister.setOnClickListener() { launchRegister() }
binding.loginTextForgotPassword.setOnClickListener() { launchPasswordForgot() }
}
private fun launchMain() {
if (binding.loginEmailEditText.text?.isEmpty() == true) {
Toast.makeText(this, "Sorry, please put in a email.", Toast.LENGTH_SHORT).show()
} else if (binding.loginPasswordEditText.text?.isEmpty() == true) {
Toast.makeText(this, "Sorry, please put in a password.", Toast.LENGTH_SHORT).show()
} else if (!isValidString(binding.loginEmailEditText.text.toString())) {
Toast.makeText(
this,
"Sorry, your email does not meet the requirements.",
Toast.LENGTH_SHORT
).show()
} else {
viewModel.login(
binding.loginEmailEditText.text.toString(),
sha256(binding.loginPasswordEditText.text.toString())
)
if (viewModel.doorgaan.value == true) {
listIntent = Intent(this, MainActivity::class.java)
startActivity(listIntent)
} else {
Toast.makeText(this, viewModel.id.value.toString(), Toast.LENGTH_SHORT).show()
// Toast.makeText(this, "Sorry, login credentials are wrong.", Toast.LENGTH_SHORT).show()
binding.loginPasswordEditText.text?.clear()
}
}
}
private fun isValidString(str: String): Boolean {
return EMAIL_ADDRESS_PATTERN.matcher(str).matches()
}
private fun launchRegister() {
listIntent = Intent(this, RegisterActivity::class.java)
startActivity(listIntent)
}
private fun launchPasswordForgot() {
listIntent = Intent(this, ForgotPasswordActivity::class.java)
startActivity(listIntent)
}
}
登錄視圖模型.kt
class LoginViewModel : ViewModel() {
private val _status = MutableLiveData<String>()
private val _id = MutableLiveData<Int>()
private val _doorgaan = MutableLiveData<Boolean>()
// The external immutable LiveData for the request status
val status: MutableLiveData<String> = _status
val id: MutableLiveData<Int> = _id
val doorgaan: MutableLiveData<Boolean> = _doorgaan
/* init {
setStatus()
}*/
fun login(email: String, password: String) {
_login(email, password)
}
private fun _login(email: String, password: String) {
viewModelScope.launch {
//val loginResult = gson.fromJson(MyApi.retroFitService.login(email,password),DataAccount::class.java)
//_status.value = loginResult
val loginResult = MyApi.retroFitService.login(email, password)
_status.value = loginResult
if (_status.value == null){
_status.value = loginResult
}
val jsonObject = JSONTokener(MyApi.retroFitService.login(email, password)).nextValue() as JSONObject
if (jsonObject.length() > 0) {
val stringArray = jsonObject.getString("data")
val jsonArray = JSONArray(stringArray)
for (i in 0 until jsonArray.length()) {
_id.value = jsonArray.getJSONObject(i).getInt("accountid")
}
_doorgaan.value = _id.value != null
}
}
}
}
MyApiService.kt
private const val baseUrl = "https://private :)/php/"
private val retrofit = Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.baseUrl(baseUrl)
.build()
interface MyApiService {
@FormUrlEncoded
@POST("LOGIN_KOTLIN.php")
suspend fun login(
@Field("email") email: String,
@Field("password") password: String
): String
}
object MyApi {
val retroFitService: MyApiService by lazy {
retrofit.create(MyApiService::class.java)
}
}
PHPAPI:
$stmt = $conn->prepare("select * FROM Account where email like ? and password like ?");
if (!$stmt){
//oeps, probleem met prepared statement!
$response['code'] = 7;
$response['status'] = 200; // 'ok' status, anders een bad request ...
$response['data'] = $conn->error;
deliver_response($response);
}
// bind parameters
// s staat voor string
// i staat voor integer
// d staat voor double
// b staat voor blob
// "ss" staat dus voor String, String
if(!$stmt->bind_param("ss", $_POST['email'], $_POST['password'])){
// binden van de parameters is mislukt
$response['code'] = 7;
$response['status'] = 200; // 'ok' status, anders een bad request ...
$response['data'] = $conn->error;
deliver_response($response);
}
if (!$stmt->execute()) {
// het uitvoeren van het statement zelf mislukte
$response['code'] = 7;
$response['status'] = $api_response_code[$response['code']]['HTTP Response'];
$response['data'] = $conn->error;
deliver_response($response);
}
$result = $stmt->get_result();
if (!$result) {
// er kon geen resultset worden opgehaald
$response['code'] = 7;
$response['status'] = $api_response_code[$response['code']]['HTTP Response'];
$response['data'] = $conn->error;
deliver_response($response);
}
// Vorm de resultset om naar een structuur die we makkelijk kunnen
// doorgeven en stop deze in $response['data']
$response['data'] = getJsonObjFromResult($result); // -> fetch_all(MYSQLI_ASSOC)
// maak geheugen vrij op de server door de resultset te verwijderen
$result->free();
// sluit de connectie met de databank
$conn->close();
// Return Response to browser
deliver_response($response);
uj5u.com熱心網友回復:
您的登錄方法是不同步的,即使協程仍在運行,該方法也會立即回傳(由于沒有時間完成,因此提供空資料)。
方法 1 - 回呼
處理此問題的一種方法是傳入這樣的回呼
fun login(email: String, password: String, onComplete: ()->Unit) {
viewModelScope.launch {
//do slow/network/suspending stuff
onComplete()
}
}
然后這樣稱呼它
viewModel.login(
binding.loginEmailEditText.text.toString(),
sha256(binding.loginPasswordEditText.text.toString())
) {
// the code in here is your "onComplete" callback, and won't run
// until the login task is done
if (viewModel.doorgaan.value == true) {
listIntent = Intent(this, MainActivity::class.java)
startActivity(listIntent)
} else {
Toast.makeText(this, viewModel.id.value.toString(), Toast.LENGTH_SHORT).show()
binding.loginPasswordEditText.text?.clear()
}
}
方法 2 - 觀察 LiveData(更好)
或者,您可以讓您的活動觀察doorgaanLiveData 并在它發生變化時做出回應,這也會導致程式適當地等待,直到那里有資料(只需確保始終為里面的資料設定一個值_login,當前代碼不會設定在某些情況下的值)。
// add this inside onCreate, and remove these calls from launchMain
viewModel.doorgaan.observe(this) { value ->
if (value == true) {
listIntent = Intent(this, MainActivity::class.java)
startActivity(listIntent)
} else {
Toast.makeText(this, viewModel.id.value.toString(), Toast.LENGTH_SHORT).show()
binding.loginPasswordEditText.text?.clear()
}
}
為了確保總是發布一些東西,你可以在里面做這樣的事情 _login
var auth = false
if (jsonObject.length() > 0) {
val stringArray = jsonObject.getString("data")
val jsonArray = JSONArray(stringArray)
for (i in 0 until jsonArray.length()) {
_id.value = jsonArray.getJSONObject(i).getInt("accountid")
}
auth = _id.value != null
}
_doorgaan.postValue(auth)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/402053.html
