Reputation: 2315
I got a problem with AsyncTask at Android Studio. What I am trying to do is before I create a new user, I am checking if the username and email exist in my database. Here is the part where I call the create AsyncTask:
new SignupAsyncTask(getBaseContext()).execute(userModel);
if(SignupAsyncTask.successCheck == false){
Toast.makeText(getBaseContext(), "Failed", Toast.LENGTH_SHORT).show();
} else if(SignupAsyncTask.successCheck == true){
Toast.makeText(getBaseContext(), "Success", Toast.LENGTH_SHORT).show();
}
Inside my AsyncTask, I am getting all user. Then I perform a loop to check if there is any matching username or password. If there is, I set the successCheck to false.
public class SignupAsyncTask extends AsyncTask<User, Integer, Boolean> {
ArrayList<User> list = new ArrayList<User>();
DB_User userCtrl = new DB_User();
Context context;
public static boolean successCheck = false;
public SignupAsyncTask(){}
public SignupAsyncTask(Context context){
this.context = context;
}
@Override
protected Boolean doInBackground(User... params) {
try {
list = userCtrl.getAllUser();
for(int i = 0; i < list.size(); i++){
User userObj = list.get(i);
if(params[0].getUserName().equals(userObj.getUserName())){
successCheck = false;
break;
}
else if (params[0].getEmail().equals(userObj.getEmail())){
successCheck = false;
break;
} else{
successCheck = true;
break;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
if(successCheck == true){
userCtrl.SignupUser(params[0]);
}
return successCheck;
}
@Override
protected void onPostExecute(Double result){
}
@Override
protected void onProgressUpdate(Integer... progress) {
}
}
The problem that I have encountered now is for the first time when I am testing with a non-duplicate username and email, it can insert into database but somehow the toast printed out 'Failed'.
Then, when I try with another duplicate record, it does not insert into database as I set my username and email to be UNIQUE but the toast is printing out 'Success'.
It is operated in the opposite way as my code logic. Any ideas?
Thanks in advance
EDIT
public class SignupAsyncTask extends AsyncTask<User, Integer, Boolean> {
ArrayList<User> list = new ArrayList<User>();
DB_User userCtrl = new DB_User();
Context lcontext;
public static boolean successCheck = false;
public SignupAsyncTask(){}
public SignupAsyncTask(Context context){
lcontext = context;
}
@Override
protected Boolean doInBackground(User... params) {
try {
list = userCtrl.getAllUser();
for(int i = 0; i < list.size(); i++){
User userObj = list.get(i);
if(params[0].getUserName().equals(userObj.getUserName())){
successCheck = false;
break;
}
else if (params[0].getEmail().equals(userObj.getEmail())){
successCheck = false;
break;
} else{
successCheck = true;
break;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return successCheck;
}
@Override
protected void onPostExecute(Boolean result){
if(successCheck)
{
//userCtrl.SignupUser(userobject);
Log.d("Check","Ran Success");
Toast.makeText(lcontext, "Success", Toast.LENGTH_SHORT).show();
}
else {
Log.d("Check","Ran Fail");
Toast.makeText(lcontext, "Failed", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onProgressUpdate(Integer... progress) {
}
Upvotes: 1
Views: 117
Reputation: 29794
It's because of AsyncTask, as its name, is an asynchronous task. You need to test the result in your SignupAsyncTask class.
Add the logic to your AsyncTask onPostExecute()
:
@Override
protected void onPostExecute(Boolean result){
if(result == false){
// Process if false
} else if(result == true){
// Process if true
}
}
Because you can't access UI thread from SignupAsyncTask (where your class is not a member class of your caller class), you need to define an interface as listener mechanism in your caller class to receive the result from your AsyncTask. So whenever there is a change in data, it will inform the caller who implements the interface.
Something like:
public interface OnSuccessCheckReceived{
void onSuccessCheckReceived(boolean isSuccess);
}
Then you add the callback interface to SignupAsyncTask:
public class SignupAsyncTask extends AsyncTask<User, Integer, Boolean> {
...
OnSuccessCheckReceived callBack;
public SignupAsyncTask(){}
public SignupAsyncTask(Context context, OnSuccessCheckReceived callBack){
this.context = context;
this.callBack = callBack;
}
...
@Override
protected void onPostExecute(Boolean result){
//if(result == false){
// // Process if false
// callBack.onSuccessCheckReceived(false); // Tell the caller
//} else if(result == true){
// // Process if true
//}
// a more compact code
callBack.onSuccessCheckReceived(result); // Tell the caller
}
Then you need to implement the listener interface to your caller class. Something like:
public class YourCallerActivity implements OnSuccessCheckReceived {
...
@Override
public void onSuccessCheckReceived(boolean isSuccess) {
if(isSuccess){
Toast.makeText(getBaseContext(), "Failed", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getBaseContext(), "Success", Toast.LENGTH_SHORT).show();
}
}
...
}
Then you must call your AsyncTask with:
// this is pointing to your implemented interface.
new SignupAsyncTask(getBaseContext(), this).execute(userModel);
Suggestion,
Better if you don't add a context to an AsyncTask, because when your app terminated and AsyncTask not yet finished its job, your AsyncTask will throw an Error because the previous context its pointing is already gone.
So you need to change your SignupAsyncTask constructor to:
public SignupAsyncTask(OnSuccessCheckReceived callBack){
//this.context = context; Remove this.
this.callBack = callBack;
}
and call the SignupAsyncTask with:
new SignupAsyncTask(this).execute(userModel);
UPDATE
As @trooper pointing out, you need to change your:
@Override
protected void onPostExecute(Double result){
}
to
@Override
protected void onPostExecute(Boolean result){
}
So to tell the caller class, you need to tell about the result:
@Override
protected void onPostExecute(Boolean result){
// This is a more compact code that your previous code.
callBack.onSuccessCheckReceived(result); // Tell the caller
}
based on the other signatures in your AsyncTask.
Upvotes: 2
Reputation: 1385
Please modify your code like this
private ArrayList<User> list;
private DB_User userCtrl;
private Context context;
private SendResponse mRes;
public SignupAsyncTask(Context context,SendResponse res){
this.context = context;
userCtrl = new DB_User();
list = new ArrayList<User>();
mRes = res;
}
@Override
protected Boolean doInBackground(User... params) {
try {
list = userCtrl.getAllUser();
for(User userObj:userCtrl.getAllUser()){
if(params[0].getUserName().equals(userObj.getUserName())
|| params[0].getEmail().equals(userObj.getEmail()))
return false;
}else{
userCtrl.SignupUser(params[0]);
return true;
}
} catch (JSONException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
protected void onPostExecute(Boolean result){
//notify through interface to activity or fragment wherever you want to
//mRes.sendResponse(result);
}
@Override
protected void onProgressUpdate(Integer... progress) {
}
Upvotes: 0
Reputation: 1488
Put your logic inside onPostExecute()
:
protected void onPostExecute(Boolean result){
if(successCheck){
Toast.makeText(getBaseContext(), "Success", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getBaseContext(), "Failed", Toast.LENGTH_SHORT).show();
}
}
AsyncTask executes asynchronously i.e., It does not run on a Main thread. It spawns a separate thread known as Worker thread, executes its logic and then post back the results onto the Main thread.
Change your code as below :
public class SignupAsyncTask extends AsyncTask<User, Integer, Boolean> {
ArrayList<User> list = new ArrayList<User>();
DB_User userCtrl = new DB_User();
Context context;
public static boolean successCheck = false;
User user = null;
public SignupAsyncTask(){}
public SignupAsyncTask(Context context){
this.context = context;
}
@Override
protected Boolean doInBackground(User... params) {
try {
user = params[0];
list = userCtrl.getAllUser();
for(int i = 0; i < list.size(); i++){
User userObj = list.get(i);
if(user.getUserName().equals(userObj.getUserName())){
successCheck = false;
break;
}
else if (user.getEmail().equals(userObj.getEmail())){
successCheck = false;
break;
} else{
successCheck = true;
break;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
return successCheck;
}
@Override
protected void onPostExecute(Boolean result){
if(result){
Toast.makeText(getBaseContext(), "Success", Toast.LENGTH_SHORT).show();
//Call SignupUser Code Here...
if(user != null) {
userCtrl.SignupUser(user);
}
} else {
Toast.makeText(getBaseContext(), "Failed", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onProgressUpdate(Integer... progress) {
}
}
Upvotes: 1