I need to press the "loginbutton" twice, before I am receiving any data. The first time I press the button, I am receiving data: "null". The second time, I am receiving the necessary data for my login. The question is: "How can I receive my data by the first clickevent?"
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"/>
LoginActivity:
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)
}
}
LoginViewModel.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);
Your login method is asnychronous, the method will return immediately even if the coroutine is still running (giving null data since it hasn't had time to complete).
Method 1 - Callback
One way of handling this would be to pass in a callback like this
fun login(email: String, password: String, onComplete: ()->Unit) {
viewModelScope.launch {
//do slow/network/suspending stuff
onComplete()
}
}
then call it like this
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()
}
}
Method 2 - Observe the LiveData (better)
Alternately, you could have your activity observe thedoorgaan
LiveData and respond when it changes, which would also cause the program to wait appropriately until it had data there (just make sure you always set a value to the data inside_login
, the current code does not set a value in some cases).
// 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()
}
}
To make sure something always gets posted, you could do something like this inside_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)
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Find the answer in similar questions on our website.
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.
PHP (from the English Hypertext Preprocessor - hypertext preprocessor) is a scripting programming language for developing web applications. Supported by most hosting providers, it is one of the most popular tools for creating dynamic websites.
The PHP scripting language has gained wide popularity due to its processing speed, simplicity, cross-platform, functionality and distribution of source codes under its own license.
https://www.php.net/
DBMS is a database management system. It is designed to change, search, add and delete information in the database. There are many DBMSs designed for similar purposes with different features. One of the most popular is MySQL.
It is a software tool designed to work with relational SQL databases. It is easy to learn even for site owners who are not professional programmers or administrators. MySQL DBMS also allows you to export and import data, which is convenient when moving large amounts of information.
https://www.mysql.com/
Welcome to the Q&A site for web developers. Here you can ask a question about the problem you are facing and get answers from other experts. We have created a user-friendly interface so that you can quickly and free of charge ask a question about a web programming problem. We also invite other experts to join our community and help other members who ask questions. In addition, you can use our search for questions with a solution.
Ask about the real problem you are facing. Describe in detail what you are doing and what you want to achieve.
Our goal is to create a strong community in which everyone will support each other. If you find a question and know the answer to it, help others with your knowledge.