-1

I have JSON data that i converted into JSONArray. I have performed this conversion in an inner class which is extending AsyncTask.

Now i have data which contains Images and their Titles. I want to create a Loop and create ImageView dynamically.

The problem i am facing is that my data is in inner class and in doInBackground() method, and the stuff; i.e: ImageView i need to create is in Outer class and in onCreate() method.

I am unable to understand how to use jsonArray which i created in my InnerClass in my outer class.

Inner Class:

public class NewsService extends AsyncTask {

    @Override
    protected JSONArray doInBackground(String... params) {

        URL url = null;
        try {
          //All JSON to JSONArray conversion code goes here
          //..

          JSONArray jsonArray = new JSONArray(jsonString);
         return jsonArray; 

Main Activity

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        NewsService newsService = new NewsService();
        newsService.execute();

//I need to use `jsonArray` in this part of my code
fadden
  • 51,356
  • 5
  • 116
  • 166
dev90
  • 7,187
  • 15
  • 80
  • 153

3 Answers3

4

I have a number of solutions for your problem.

  1. On the top what comes into my mind is that you pass the context of activity class as a data member of your async task class, then when the work is donein onPostExecute

    ((YourActivityName)context).createDynamicImages(yourJsonArray);

Before this you will need to save the context of your activity as data member of async task class

YourAsyncTask task = new YourAsyncTask(this);
task.execute();

and so the constructor of your async task class will become

public YourAsyncTask(Context context){
    this.context = context;
}
Atif Rehman
  • 325
  • 1
  • 12
2

One easy way to do this is defining an interface as your AsyncTask's callback. Here is an example :

public interface Callback {
    void processData(DataType data);
}

and in your MainActivity you should implement that interface :

public class MainActivity extends Activity  implements Callback {
    ...
    void processData(DataType data) {
     //your code here
    }
}

and in your calling code :

new NewService(this).execute();

and your NewService class :

public class NewService extends AsyncTask ... {
    ...
    Callback cb;
    public NewService(Callback cb) {
    this.cb = cb;
    }
    ...
}

and call your Callback method in onPostExecute

void onPostExecute(DataType data) {
    cb(data);
}
Mohammad Rahchamani
  • 5,002
  • 1
  • 26
  • 36
  • of course It's better to use `WeakReference` for your `Callback` instance in your `AsyncTask` class. – Mohammad Rahchamani Apr 07 '16 at 18:09
  • Do not make the async task an inner class, but a static inner class. This will decouple the task itself from the UI and you'll prevent activity memory leaks caused by potential configuration changes (screen rotates, user changes language, etc..). The task can then report back using the callback system. – Ryhan Apr 07 '16 at 20:41
  • @Ryan I suggest to create a separate class for `AsyncTask` to re-use it anywhere you want. – Mohammad Rahchamani Apr 07 '16 at 21:28
0

AsynTask.doInBackground runs on the Background, Not on the main thread, So you should use onPostExecute (this method runs after the task is done) in case you want process data on the main thread including UI updates, You can achieve that with using an interface inside your AsyncTask class:

    interface OnJsonArrayReceive {
    void onReceive(JSONArray array);
    }

AsyncTask class will look like this:

   class SomeTask extends AsyncTask<String, Void, JSONArray> {

    OnJsonArrayReceive mOnJsonArrayRecieve;

    public SomeTask(OnJsonArrayRecieve listener) {
        mOnJsonArrayRecieve = listener;
    }

    @Override
    protected JSONArray doInBackground(String... params) {
        //do something with and return your array
        //this runs on background
        return jsonArray;
    }

    @Override
    protected void onPostExecute(JSONArray jsonArray) {
        //This runs on main thread
        if (mOnJsonArrayReceive != null) {
            mOnJsonArrayReceive.onReceive(jsonArray);
        }
    }
}

This class takes a OnJsonArrayRecieve listener as argument (that is implemented in the MainActivity) and when the data process on background is done onRecieve will be called, use it in your code like this :

    new SomeTask(new OnJsonArrayRecieve() {
        @Override
        public void onReceive(JSONArray array) {
            //do something with json array
        }
        }).execute(someArgument);
Farshad
  • 3,074
  • 2
  • 30
  • 44