0

in this below code i want to return value from AsyncTask with using an Interface. but i get wrong value and i can not return correct value from onPostExecute.

i'm developed this link tutorials with my code. i can not use correctly with that.

Interface:

public interface AsyncResponse {
    void processFinish(String output);
}

Ksoap Main class:

public class WSDLHelper  implements AsyncResponse{
    public SoapObject request;

    private String Mainresult;

    public String call(SoapObject rq){

        ProcessTask p =new ProcessTask(rq);
        String tmp = String.valueOf(p.execute());

        p.delegate = this;

        return Mainresult;
    }


    @Override
    public void processFinish(String output) {

        this.Mainresult = output;
    }
}
class ProcessTask extends AsyncTask<Void, Void, Void > {
    public AsyncResponse delegate=null;

    SoapObject req1;
    private String result;
    public ProcessTask(SoapObject rq) {
        req1 = rq;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Void doInBackground(Void... params) {

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.setOutputSoapObject(this.req1);

        AndroidHttpTransport transport = new AndroidHttpTransport(Strings.URL_TSMS);
        transport.debug = true;

        try {
            transport.call(Strings.URL_TSMS + this.req1.getName(), envelope);
            this.result = envelope.getResponse().toString();
        } catch (IOException ex) {
            Log.e("" , ex.getMessage());
        } catch (XmlPullParserException ex) {
            Log.e("" , ex.getMessage());
        }

        if (result.equals(String.valueOf(Integers.CODE_USER_PASS_FALSE))) {
            try {
                throw new TException(PublicErrorList.USERNAME_PASSWORD_ERROR);
            } catch (TException e) {
                e.printStackTrace();
            }

        }

        Log.e("------------++++++++++++++++-----------", this.result);

        return null;
    }

    protected void onPostExecute(String result) {
    /* super.onPostExecute(result);*/
        delegate.processFinish(this.result);
    }

}

please help me to resolve this problem

Community
  • 1
  • 1
Mahdi Pishguy
  • 109
  • 1
  • 7

2 Answers2

2

That can't work. You are creating and executing the AsyncTask (asynchronously!) and then call return Mainresult (synchronously!) when it hasn't received the result yet. The solution is to remove the redundant class WSDLHelper and access ProcessTask directly

Beside that, you're using AsyncTask incorrectly (saving the result in a class variable instead of passing it as a parameter). Here's the full version:

public class ProcessTask extends AsyncTask<Void, Void, String> {
public AsyncResponse delegate=null;

SoapObject req1;

public ProcessTask(SoapObject rq, AsyncResponse delegate) {
    req1 = rq;
    this.delegate = delegate;
}

@Override
protected void onPreExecute() {
    super.onPreExecute();
}

@Override
protected Void doInBackground(Void... params) {

    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.setOutputSoapObject(this.req1);

    AndroidHttpTransport transport = new AndroidHttpTransport(Strings.URL_TSMS);
    transport.debug = true;

    String result = null;
    try {
        transport.call(Strings.URL_TSMS + this.req1.getName(), envelope);
        result = envelope.getResponse().toString();
    } catch (IOException ex) {
        Log.e("" , ex.getMessage());
    } catch (XmlPullParserException ex) {
        Log.e("" , ex.getMessage());
    }

    if (result != null && result.equals(String.valueOf(Integers.CODE_USER_PASS_FALSE))) {
        try {
            throw new TException(PublicErrorList.USERNAME_PASSWORD_ERROR);
        } catch (TException e) {
            e.printStackTrace();
        }

    }

    Log.e("------------++++++++++++++++-----------", result);

    return result;
}

protected void onPostExecute(String result) {
/* super.onPostExecute(result);*/
    delegate.processFinish(result);
}

}

Now you would execute ProcessTask from outside like this, which will make sure you receive the result asynchronously:

new ProcessTask(rq, new AsyncResponse() {
    @Override
    public void processFinish(String output) {
        // do whatever you want with the result
    }
}).execute();
0101100101
  • 5,786
  • 6
  • 31
  • 55
  • Thanks sir. how can i develop `call` method in `WSDLHelper`? i get error in `Contsructor` in `ProcessTask p =new ProcessTask(rq); `i'm change that to `public String call(SoapObject rq){ ProcessTask p =new ProcessTask(rq,this); /*String tmp = String.valueOf(p.execute()); p.delegate = this;*/ return MainResult; }` but thats not correct. – Mahdi Pishguy Sep 10 '14 at 07:35
  • Oh actually, I haven't seen your "p.delegate = this". That's wrong in so many ways ... You haven't understood the concept of interfaces. You're executing an AsyncTask and expect to immediately return its result. It's asynchronous, so that's impossible! I will update my answer. – 0101100101 Sep 10 '14 at 07:47
  • I'm sorry sir. i'm develop you update code to http://paste.debian.net/120158/ . but thats wrong and return `NullPointerException`. – Mahdi Pishguy Sep 10 '14 at 07:59
  • ***REMOVE*** WSDLHelper. ***Do not return "Mainresult"***, it's null because ProcessTask returns its result asynchronously! ***Handle the result INSIDE processFinish()***. If you're not able to grasp this, you must read [Processes and Threads](http://developer.android.com/guide/components/processes-and-threads.html) -- no one can help you otherwise. – 0101100101 Sep 10 '14 at 08:07
  • Excuse me. i read that link before your send topic but i'm using `call` method form `WSDLHelper` in all of project and i must be return result from it to use other methods and i can not **Remove** `WSDLHelper`. can i return result from it after get output with `processFinish`.for example: `LoginFields loginSoapParser = tsms.SoapParser(wsdlHelper.call(tsms.SoapObjectRequest));` please help me thanks – Mahdi Pishguy Sep 10 '14 at 08:15
  • No you can't. processFinish() runs in a different thread -- not the one that called wsdlHelper.call(...), so call(...) returns before processFinish() is executed. You can only do something **inside processFinish()**. You can either directly update any views there (call setText(output) on a TextView, for example) or pass the result to other objects implementing AsyncResponse and do something there. I can't help you further, I was more thorough than most people on StackOverflow would be. You're on your own now. – 0101100101 Sep 10 '14 at 08:43
0

Your result will always be null, because you return null in the doInBackground() method. The value you return in doInBackground() will be passed to onPostExecute(). Change your AsyncTask<Void, Void, Void> to AsyncTask<Void, Void, String>, and return the result. This will call onPostExecute(String result) with the correct result.

Perhaps this link might help you a bit: http://bon-app-etit.blogspot.be/2012/12/using-asynctask.html

dumazy
  • 13,857
  • 12
  • 66
  • 113