NUIG2014
NUIG2014

Reputation: 197

Instance of class that extends Asynctask doesn't fully work

Hi I'm just trying to get a user Login and registration form going for Android and I ran into a little problem and I can't make sense of it. I'm fairly new to Programming so bear with me.

I have a main activity class and a Register activity class that extends AsyncTask and connects to a PHP file. When I send the details to the PHP file I get a response of either one or zero indicating if a user exists or not. In my main method I execute the Register class by creating an instance of it, and the user credentials get stored to the database if the email doesn't exist and not if it does exist. My problem is what I get in response doesn't seem to transfer back to my main class through using getters and setters. I have tested the response in the Register class and a "1" or "0" is returned, but by calling the getter from the main class to access the response a null is returned. Also the the output to logcat gets printed from the main class before the Register class prints the value. If anyone could help I would greatly appreciate it.

package com.eanna.UserLogin;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class Main extends Activity  {

private EditText username;
private EditText firstname;
private EditText surname;
private EditText password;
private EditText email;
private Button register;
private ProgressDialog pDialog;




@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

     username=(EditText) findViewById(R.id.editText1);
     firstname=(EditText) findViewById(R.id.editText2);
     surname=(EditText) findViewById(R.id.editText3);
     password=(EditText) findViewById(R.id.editText4);
     email=(EditText) findViewById(R.id.editText5);
    register=(Button) findViewById(R.id.button1);

}

        public void register(View v) {


            String usernameStr = username.getText().toString();
            String firstnameStr = firstname.getText().toString();
            String surnameStr = surname.getText().toString();
            String passwordStr = password.getText().toString();
            String emailStr = email.getText().toString();


              register registerInst = new register();
                  registerInst.execute(usernameStr,firstnameStr,surnameStr,passwordStr,emailStr);
              System.out.println("Response Value(main class) is: "+registerInst.getValue() );

        }


}

My register class

package com.eanna.UserLogin;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

import android.os.AsyncTask;

public class register extends AsyncTask<String, Void, String> {


    String value;

@Override
protected String doInBackground(String... arg0) {
    // TODO Auto-generated method stub
     try{
            String username = (String)arg0[0];
            String firstname = (String)arg0[1];
            String surname = (String)arg0[2];
            String password = (String)arg0[3];
            String email = (String)arg0[4];


            String link = "http://randomsite.com/randomphpfile.php";
            String data=URLEncoder.encode("username", "UTF-8")
                    + "=" + URLEncoder.encode(username, "UTF-8");
            data+="&"+URLEncoder.encode("firstname", "UTF-8")
                    + "=" + URLEncoder.encode(firstname, "UTF-8");
            data+="&"+URLEncoder.encode("surname", "UTF-8")
                    + "=" + URLEncoder.encode(surname, "UTF-8");
            data+="&"+URLEncoder.encode("password", "UTF-8")
                    + "=" + URLEncoder.encode(password, "UTF-8");
            data+="&"+URLEncoder.encode("email", "UTF-8")
                    + "=" + URLEncoder.encode(email, "UTF-8");


            URL url = new URL(link);

            URLConnection conn = url.openConnection(); 
            conn.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter
            (conn.getOutputStream()); 

            wr.write( data ); 
            wr.flush(); 
            BufferedReader reader = new BufferedReader
            (new InputStreamReader(conn.getInputStream()));
            StringBuilder sb = new StringBuilder();
            String line = null;
//               Read Server Response
            while((line = reader.readLine()) != null)
            {
               sb.append(line);
               break;
            }


            return sb.toString();
         }catch(Exception e){
            return new String("Exception: " + e.getMessage());
         }

      }
 @Override
   protected void onPostExecute(String result){
      setValue(result);
      System.out.println("Response Value (Register class) is: "+result);

   }


 public void setValue(String value){
     this.value=value;

 }

 public String getValue(){
     return value;
 }

}

Here is my output

03-03 19:53:12.302: D/libEGL(1091): loaded /system/lib/egl/libEGL_emulation.so
03-03 19:53:12.312: D/(1091): HostConnection::get() New Host Connection established 0x2a1f1df8, tid 1091
03-03 19:53:12.392: D/libEGL(1091): loaded /system/lib/egl/libGLESv1_CM_emulation.so
03-03 19:53:12.405: D/libEGL(1091): loaded /system/lib/egl/libGLESv2_emulation.so
03-03 19:53:12.482: W/EGL_emulation(1091): eglSurfaceAttrib not implemented
03-03 19:53:12.492: D/OpenGLRenderer(1091): Enabling debug mode 0
03-03 19:53:12.562: D/dalvikvm(1091): GC_FOR_ALLOC freed 78K, 8% free 2942K/3176K, paused 47ms, total 51ms
03-03 19:53:17.623: I/System.out(1091): Response Value(main class) is: null
03-03 19:53:18.049: I/System.out(1091): Response Value (Register class) is: 1

It outputs the main classes system.out first even though that was supposed to execute after the

" registerInst.execute(usernameStr,firstnameStr,surnameStr,passwordStr,emailStr);"

Thanks for any help.

Upvotes: 1

Views: 208

Answers (4)

Zied R.
Zied R.

Reputation: 4964

There is two threads : one for the AsyncTask , and one for the main class

For the first (AsyncTask) : it can take several time to complete its task , and complete after the second thread (Main) .

So that System.out.println("Response Value(main class) is: "+registerInst.getValue() ); can show the results before System.out.println("Response Value (Register class) is: "+result);

Upvotes: 0

seeming.amusing
seeming.amusing

Reputation: 1179

Your first println statement (Response Value(main class)) will always be executed right away, which is why it prints null. Your register class will then do the processing on a separate thread and print the fetched value. In other words, your first println statement will never be called after you have finished fetching the content.

What you may want to consider doing is adding a callback interface to your register class. This way, your Activity can implement it, pass it to your AsyncTask implementation, which will then trigger the callback when it is done. For example:

The interface:

public interface Callback {
    void onComplete(String response);
}

And in your register class:

private Callback mCallback;

public void setCallback(Callback callback) {
    mCallback = callback;
}

@Override
public void onExecute(String result) {
    mCallback.execute(result);
}

Upvotes: 1

Sushil
Sushil

Reputation: 8488

As you main class.out is part of main thread and reisterInst.execute starts a thread, so this behavior is fine that "System.out.println("Response Value(main class) is: "+registerInst.getValue() );" line is executed before the parallel thread completes execution. The UI thread is not blocked after it starts AsyncTask and thats how it should be. The purpose of starting AsyncTask is that we do not want to block UI/Main Tread.

This is the reason why your getVialue() is returning 0 as its gets executed before your asynctask completes. You can write a handler in MainClass and post the result to handler.

Upvotes: 1

Merlevede
Merlevede

Reputation: 8180

First be careful with your register variable. You defined it first as

register=(Button) findViewById(R.id.button1);

and then as

register registerInst = new register();

This is not necessarily a bug but definitely bad practice.

What you say about It outputs the main classes system.out first even though that was supposed to execute after the... is not a bug. The AsyncTask (e.g. your register variable) runs in the background on a separate thread. When you call execute there's no guarantee on how the threads are going to be performing concurrently. Ultimately, that's what AsyncTask is designed for, to do some heavy processing (web requests...) without blocking the main thread!

Upvotes: 2

Related Questions