我真的很想解决一个简单的问题,希望有人可以提供帮助。
我有一个使用基本查询对数据库进行身份验证的基本应用程序。此查询在async doinbackground中运行并返回一个名为isSuccess的布尔值。
然后将其传递给按钮onclick方法,该方法然后确定用户是否输入了正确的密码。在异步方法上,布尔值将重新初始化为true。
我遇到的问题是,似乎在onclick阶段它会获取初始化的布尔值,而不是indobackground部分中更改后的变量值。
issueing.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
String passwordd = password.getText().toString();
CheckLogin checkLogin = new CheckLogin();// this is the Asynctask, which is used to process in background to reduce load on app process
checkLogin.execute(passwordd,passwordd);
password.getText().clear();
if (checkLogin.isSuccess)
Toast.makeText(MainActivity.this, "Issue Login", Toast.LENGTH_SHORT).show();
}
});
}
public class CheckLogin extends AsyncTask<String, String, String>
{
String z = "";
boolean isSuccess = true;
@Override
protected void onPreExecute()
{
//progressBar.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(String r)
{
}
@Override
public String doInBackground(String... args)
{
String usernam = args[0];
String passwordd = args[1];
{
try
{
Class.forName("net.sourceforge.jtds.jdbc.Driver");
con = DriverManager.getConnection(db, un, pass); // Connect to database
if (con == null)
{
z = "Check Your Internet Access!";
}
else {
String query = " select * from employee where password = '"+ passwordd+"'" ;
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
String employee,pw;
if (rs.next()) {
employee= rs.getString("employee");
pw = rs.getString("password");
z = "Success";
//setSuccess(true);
isSuccess = true;
}
else if (!rs.next())
{
//setSuccess(false);
//setSuccess(false);
isSuccess = false;
z = "Invalid Password";
}
}
}
catch (Exception ex)
{
isSuccess = false;
//setSuccess(false);
z = ex.getMessage();
}
}
return null;
}
我怀疑onclick不能及时获得更改后的布尔值,因为它在后台运行。
答案 0 :(得分:1)
这仅仅是因为当您使用以下代码时:
CheckLogin checkLogin = new CheckLogin();
checkLogin.execute(passwordd,passwordd);
password.getText().clear();
if (checkLogin.isSuccess)
Toast.makeText(MainActivity.this, "Issue Login", Toast.LENGTH_SHORT).show();
}
您正在考虑代码以同步方式工作。 CheckLogin
是一个异步工作的AsyncTask。因此,以下代码中的CheckLogin代码:
CheckLogin checkLogin = new CheckLogin();
checkLogin.execute(passwordd,passwordd);
将执行一个单独的任务,并且在完成其工作之前不会阻塞该进程。因此,在您的以下代码中吐司:
if (checkLogin.isSuccess)
Toast.makeText(MainActivity.this, "Issue Login", Toast.LENGTH_SHORT).show();
}
由于checkLogin.isSuccess仍然为false,因此不会执行。
简单的解决方法是将支票移至AsyncTask的onPostExecute
。像这样:
@Override
protected void onPostExecute(String r) {
if (checkLogin.isSuccess) {
// do something with the success
}
}
正确的方法是通过使用监听器作为回调机制来告知活动该过程已完成。这会将您的Activity和AsyncTask流程分开,以使其在将来更加可维护。
您可以使用AsyncTask和类似以下内容的回调:
public class CheckLoginTask extends AsyncTask<Void, Void, Boolean> {
private String mUserName;
private String mPassword;
private ResultListener mListener;
private String mMessage;
public interface ResultListener {
void onSuccess(String message);
void onFailure(String message);
}
public CheckLoginTask(String userName, String password, ResultListener listener) {
mUserName = userName;
mPassword = password;
mListener = listener;
}
@Override protected Boolean doInBackground(Void... voids) {
boolean isSuccess = false;
// do some process with username and password
// assume there is a a message
mMessage = "Invalid password";
return isSuccess;
}
@Override protected void onPostExecute(Boolean isSuccess) {
if(isSuccess) {
mListener.onSuccess(mMessage);
} else {
mListener.onFailure(mMessage);
}
}
}
可以这样使用:
CheckLoginTask.ResultListener listener = new CheckLoginTask.ResultListener {
@Override
public void onSuccess(String message) {
// do something when success
}
@Override
public void onFailure(String message) {
// do something with failure
}
};
CheckLoginTask checkLoginTask = new CheckLoginTask(userName, password, listener);
checkLoginTask.execute();
答案 1 :(得分:0)
对于我从您的问题中了解的内容,您想检查一下 密码,然后将结果传递到活动或其他地方。
由于AsyncTasks在不同的线程上运行,因此它们具有与主线程联系的方法,例如onPreExecute()
和onPostExecute(String r)
,因此您需要执行以下操作:
创建一个看起来像这样的界面:
public interface PasswordChecker {
void onChecked(Boolean isSuccess);
}
第二件事是使您的活动或类实现此接口,方法如下:
public class MyActivity extends AppCompatActivity implements PasswordChecker {
@Override
public void onChecked(Boolean isSuccess) {
if (isSuccess) {
//Do Stuff with your isSuccess Boolean
}
}
}
或者您可以初始化PasswordChecker对象变量,并将其作为参数传递给第三步。
使您的AsyncTask要求使用PasswordChecker,然后必须将活动或类或对象作为构造函数的参数传递,您的AsyncTask如下所示:
public class CheckLogin extends AsyncTask<String,String,Boolean> {
private PasswordChecker checker;
CheckLogin(PasswordChecker checker) {
this.checker = checker;
}
@Override
protected Boolean doInBackground(String... strings) {
boolean isSuccess;
//Do Your Work..
//...
//...
//if (condition)
isSuccess = true;
return isSuccess;
}
@Override
protected void onPostExecute(Boolean isSuccess) {
super.onPostExecute(isSuccess);
checker.onChecked(isSuccess);
}
}
最后,您必须使用PasswordChecker对象作为参数来初始化AsyncTask:
//Passing the activity it self (which implements PasswordChecker) as an argument
final CheckLogin checkLogin = new CheckLogin(MyActivity.this);
或
//Or by passing a custom object
PasswordChecker myChecker = new PasswordChecker() {
@Override
public void onChecked(Boolean isSuccess) {
if (isSuccess) {
Toast.makeText(MyActivity.this , "Login Success!" , Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(MyActivity.this , "Login Failed!" , Toast.LENGTH_LONG).show();
}
}
};
CheckLogin myCheckLogin = new CheckLogin(myChecker);
//Do the rest of the job
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Execute your task
checkLogin.execute("Username", "Password");
}
});
onPostExecute(String r)
传递,每次checker.onChecked(isSuccess);
被触发时,您的界面都会被触发(onPostExecute
)调用,将布尔值作为参数传递,并根据其值执行其中的代码。答案 2 :(得分:-1)
问题是doInBackground()
工作的线程与onClick()
不同。 onClick()
适用于UIThread。因此您不会收到对该线程的任何更新。
首先将您的异步任务声明更改为此:
public class CheckLogin extends AsyncTask<Void, Void, Boolean>
第三个参数是doinbackground返回的结果参数。
因此您的doInBackground()
和onPostExecute()
将会是这样:
@Override
protected Boolean doInBackground(Void... params) {
if(some_condition) {
return true;
} else {
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
// use the result
super.onPostExecute(result);
isSuccess = result;
};
答案 3 :(得分:-1)
您必须输入以下行:
Toast.makeText(MainActivity.this, "Issue Login", Toast.LENGTH_SHORT).show();
在onPostExecute()
内。
方法onClick()
在另一个线程上运行。
因此,当您进行此检查时:
if (checkLogin.isSuccess) {...}
很有可能doInBackground()
内的代码尚未完成,因此在onClick()
内可以得到isSuccess
的初始值true
。