How to implement a ProgressDialog while an Activity requests a SoapObject from a web service?

I know that questions from ProgressDialog with Threads have been asked many times, but none of the solutions seem to work for my project. Basically, what I want to do is: 1) when the user clicks the button, the action sends an auth request to the server 2) while this is done, ProgressDialog is displayed 3) when the response comes, I want to reject the ProgressDialog and the returned object that should be read and interpreted by Activity.

If I: 1) set Thread to update the Application field with the answer, the next method (which is outside of Thread) gives NPE when accessing the field 2) if I include the next method in Thread, the second method throws "java.lang.RuntimeException: not manages to create a handler inside a thread that did not call Looper.prepare () "

Sorry for the long text, but I completely lose it for this ... My code is this:

public class XXX extends Activity implements OnClickListener {

// (...)
private SoapObject returnObject;
private String response;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // (...)
        authProgressDialog = ProgressDialog.show(XXX.this, "", "Authenticating...", true, false);
        new Thread(new Runnable() {
            @Override
            public void run() {
                authenticate(); // method that calls the API via SOAP
                authenticateReal(); // method that handles the response
            }
        }).start();

        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what) {
                    case 10:
                        authProgressDialog.dismiss();
                        break;
                }
            }
        };
    }
}

public void authenticate() {
    // API stuff (...)
    AndroidHttpTransport aht = new AndroidHttpTransport(URL);
    try {
        aht.call(SOAP_ACTION, soapEnvelope);
        returnObject = (SoapObject) soapEnvelope.getResponse();
        response = returnObject.getProperty("ResponseStatus").toString();
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        mHandler.sendEmptyMessage(10);
    }
}

// Method that needs to access returnObject and reponse objects and
// it is here where the NPE or other exceptions are thrown
public void authenticateReal() {
// (...)
}
+3
source share
4 answers

Better to use AsyncTask(this is Android way):

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

    new TheTask().execute();
}

private class TheTask extends AsyncTask<Void, Void, Void>{

    @Override
    protected void onPreExecute() {
        authProgressDialog = ProgressDialog.show(XXX.this, "", "Authenticating...", true, false);
    }

    @Override
    protected Void doInBackground(Void... params) {
        authenticate(); // method that calls the API via SOAP
        authenticateReal(); // method that handles the response
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        authProgressDialog.dismiss();
    }
}

By the way ... I found this presentation very useful (it talks about REST applications, but you can apply the same concept for different types of applications): Development Android REST client applications

+8

"Looper.prepare();" run().

        @Override
        public void run() {
            Looper.prepare();
            authenticate(); // method that calls the API via SOAP
            authenticateReal(); // method that handles the response
        }

, authenticate()? ( LogCat )

AsyncTask ( ).

+2

Thread AsyncTask, :

public class XXX extends Activity implements OnClickListener {
...
    private static int HANDLER_MESSAGE_AUTH_REQUEST_COMPLETE = 10;
...
    private void performAuthentication(){
        authProgressDialog = ProgressDialog.show(XXX.this, "", "Authenticating...", true, false);
        Thread backgroundThread = new Thread() {
            @Override
            public void run() {
                authenticate();
            }
        }
        backgroundThread.start();
    }

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what){
            case HANDLER_MESSAGE_AUTH_REQUEST_COMPLETE:
                authProgressDialog.dismiss();
                break;
            }
        }
    }

    private void authenticate(){
        // existing authenticate code goes here
        ...
        Message msg = Message.obtain();
        msg.what = HANDLER_MESSAGE_AUTH_REQUEST_COMPLETE;
        handler.sendMessage(msg);
        // existing authenticateReal code goes here
        ...
    }
}

100% , mHandler new Handler(). , private class. authenticate(), , , .

+1

, AsyncTask - .

: AsyncTask Threads :

android:configChanges="keyboardHidden|orientation" (, onConfigChange ) Manifest.xml, Activity ContentView, ProgressDialog ( ). Android Thread AsyncTask. , . , .

Trying to reject () your previously created ProgressDialog throws an exception after the ContentView has been destroyed, since it is no longer part of your window. try / catch LOT in situations doing something taken off (asynchronous) action. Everything you could possibly rely on could simply disappear or replace with something else when onPostExecute () is called again. Finally, think about registering every ASyncTask that you run in some kind of array in your activity, and try undoing () them on your Activity.onDestroy ().

+1
source

Source: https://habr.com/ru/post/1787330/


All Articles