1

Generally I update UI in postExecute method.
e.g.

public class SampleActivity extends Activity{
TextView textSample;
@Override
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


        setContentView(R.layout.aadd_addtocheck);
        textSample = (TextView) findViewById(R.id.lin);
                STask sampleTask = new Stask();
                sampleTask.execute();
}
class GetAdd extends AsyncTask<Void, Void, JSONObject> {


        @Override
        protected JSONObject doInBackground(Integer... params) {
            // TODO Auto-generated method stub
            UserFunctions u = new UserFunctions();
            return u.getNewAdd();
        }

        @Override
        protected void onPostExecute(JSONObject result) {
            super.onPostExecute(result);
                    textSample.setText(result.getString("Something");
}

However, my asyncTask become large and I want to move them to different class (before they were a subclass). Therefor, I wonder how to to update UI ( like setting texviews) when asynctask will be a separete class.

Yarh
  • 4,459
  • 5
  • 45
  • 95
  • [See this answer](http://stackoverflow.com/questions/18517400/inner-class-can-access-but-not-update-values-asynctask/18517648#18517648) about using an `interface` with `AsyncTask` – codeMagic Oct 23 '13 at 18:09

3 Answers3

2

You pass either the Context, Activity, or the individual Views to the AsyncTask's constructor and store them as member variables, then update them on onPostExecute().

Be sure to store Context or Activity as a WeakReference to prevent memory leaks.

Piovezan
  • 3,215
  • 1
  • 28
  • 45
1

If you are going to put the AsyncTask in a separate file, you might be likely to reuse that AsyncTask from other Activities, so I think that the best practise would be to make a callback to the activity so it does all the UI handling.

For doing that what you should do is create an Interface like the following:

public interface OnGetAddCompletedListener {
    public void onGetAddCompleted(String text);
}

Receive the callback in the constructor of your AsyncTask and call the method in it in onPostExecute

public class GetAdd extends AsyncTask<Void, Void, JSONObject> {

    private OnGetAddCompletedListener callback;

    public GetAdd(OnGetAddCompletedListener callback) {
        this.callback = callback;
    }

    @Override
    protected JSONObject doInBackground(Integer... params) {
        // TODO Auto-generated method stub
        UserFunctions u = new UserFunctions();
        return u.getNewAdd();
    }

    @Override
    protected void onPostExecute(JSONObject result) {
        super.onPostExecute(result);
        callback.onGetAddCompleted(result.getString("Something");
    }
}

And then, implement the interface in the Activity you are executing it so it handles the UI modifications when you get the data in the AsycTask:

public class SampleActivity extends Activity implements OnGetAddCompletedListener {
    TextView textSample;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


        setContentView(R.layout.aadd_addtocheck);
        textSample = (TextView) findViewById(R.id.lin);
                STask sampleTask = new Stask();
                sampleTask.execute();
    }

    public void onGetAddCompleted(String text) {
        textSample.setText(text);
    }
}

With this approach, if you decide to reuse that AsyncTask from other activity you will be able to do different things when the AsyncTask has ended in case you want to do so.

josebama
  • 848
  • 8
  • 11
  • I am a bit confused about one thing - if i have 2 running activity which implements OnGetAddCompletedListener; one of them starts asyncTask. When async task will be finished callback will be recieved by both activity or only by activity which started asynctask? – Yarh Oct 23 '13 at 19:35
  • 1
    With this approach what you are doing is putting a _refference_ to the calling Activity (or wherever you are executing the `AsyncTask` from so when the `onPostExecute` will call the method `onGetAddCompleted` implemented in the Activity you are calling it from. So, if you have ActivityA and ActivityB both implementing `OnGetAddCompletedListener`, when you execute the `AsyncTask` from ActivityA, the `onPostExecute` will call the method implemented in ActivityA and when you execute it from ActivityB `onPostExecute` will call the method implemented in AcitivityB – josebama Oct 24 '13 at 09:34
0

You can pass arguments into the constructor of your AsyncTask when you call it. Let's say that in your main activity you have the following:

TextView tv = (TextView) findViewById(R.id.my_text_view);
Stask sampleTask = new Stask(tv);
sampleTask.execute();

When you are creating your AsyncTask, you have:

class Stask extends AsyncTask ...(){
    final TextView textView; 

    public Stask(Textview inputFromOtherClass){
        this.textView = inputFromOtherClass;
    }
}

This way, the TextView created in your main activity can exist as an instance in your AsyncTask.

EDIT:As someone else posted, you can do something similar for the Context, which is useful in creating various instances.

mike
  • 1,318
  • 3
  • 21
  • 41