eric_spittle
eric_spittle

Reputation: 124

AsyncTask to call another function within class

Basically, do I have to put code I want to run on another thread inside doInBackground, or can I call another function/class/whatever-it-is-functions-are-called-in-JAVA within doInBackground and have it run asynchronously? IE: (example code I found online)

      protected String doInBackground(String... params) {
        for(int i=0;i<5;i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        TextView txt = (TextView) findViewById(R.id.output);
        txt.setText("Executed");
        return null;
  }  

is how I have seen it done, but can I instead do:

      protected String doInBackground(String... params) {
           postToServer(x,y,z,h);
      }  

and have it call a function I already wrote and then have that function run in another thread? Sometimes my HTTP server is a bit slow to respond (it is but a lowly testing server at the moment) and Android automatically pops up the kill process box if my postToServer() call takes more than 5 seconds, and also disables my UI until the postToServer() call finishes. This is a problem because I am developing a GPS tracking app (internally for the company I work for) and the UI option to shut the tracking off freezes until my postToServer() finishes, which sometimes doesn't ever happen. I apologize if this has been answered, I tried searching but haven't found any examples that work the way I'm hoping to make this work.

Upvotes: 2

Views: 7811

Answers (4)

Justin Sharma
Justin Sharma

Reputation: 1

Basically The Bottom Line Is the doInBackground() method is Can't interact with The Ui Thread Or The Main thread. that's Why When You are Try To Interact With The TextView in doInBackground () it Will Crash the UI Thread Cuz It's Illegal. so if anytime You want to Interact with the UI Thread,When You are Working on doInBackground You need to Override OnPostExecute() //this Function is Called when The doInBackground Function job is Done. So You can Update The UI Thread Content By this When You're Job is Done In doInBackground () or You are In doInBackground ()

Upvotes: -1

TeamBanana
TeamBanana

Reputation: 179

Yes you can, the call to your postToServer method (that's the name in java) will run off the main thread. Everything inside the doInBackground method of an AsyncTask is run on a pooled thread, but be sure to NOT invoke it directly! Call execute on your asynktask instead, the android framework will do the work for you and run doInBackground on another thread.

try doing something like this:

new AsyncTask<Void, Void, Void>() {
    @Override
    // this runs on another thread
    protected Void doInBackground(Void... params) {
        // assuming x, y, z, h are visible here
        postToServer(x, y, z, h);
        return null;
    }

    @Override
    // this runs on main thread
    protected void onPostExecute(Void result) {
        TextView txt = (TextView) findViewById(R.id.output);
        txt.setText("Executed");
    }

}.execute(); // call execute, NOT doInBackGround

Also, notice that every other method of AsyncTask, such as onPostExecute runs on the main thread, so avoid heavy loading them.

Upvotes: 1

FoamyGuy
FoamyGuy

Reputation: 46856

Have you tried it the second way?

From what you've posted it seems like it should work fine how you have it in the second example.

However (perhaps unrelated to your question?) in your first example I think it will fail because you are trying to change the UI from a background thread. You'd want to put the parts that manipulate the TextView inside of onPostExecute() rather than doInBackground()

Upvotes: 1

antew
antew

Reputation: 7478

You can do that, but you will have to move the UI updates to onPostExecute as it is run on the UI thread.

public MyAsyncTask extends AsyncTask<foo, bar, baz> {

    ...

    protected String doInBackground(String... params) {
       postToServer(x,y,z,h);
    }  

    protected void onPostExecute(Long result) {
        TextView txt = (TextView) findViewById(R.id.output);
        txt.setText("Executed");
    }

    ....

}

You may want to pass in the TextView to the constructor of the AsyncTask and store it as a WeakReference. private final WeakReference textViewReference;

public MyAsyncTask(TextView txt) {
    textViewReference = new WeakReference<TextView>(txt);
}

And then in onPostExecute you would make sure that the TextView reference still exists.

protected void onPostExecute(Long result) {
    TextView txt = textViewReference.get();
    if (txt != null)
        txt.setText("Executed");
}

If you want to notify the user that the task is executing I would put that before invoking the AsyncTask.

 myTextView.setText("Update in progress...");
 new MyAsyncTask().execute();

then in onPostExecute set the TextView to say "Update complete."

Upvotes: 3

Related Questions