user1515520
user1515520

Reputation: 634

android: using arrayadapter<Custom object> that was created in AsyncTask in the MainActivity

I got the following problem and hope someone could give me a hint.

I have an activity that executes an AsyncTask< String, Void, ArrayList<Custom object >>. In the doInBackground() function, I set up a new ArrayList of custom objects which is also the return value. In the onPostExecute() method that ArrayList is used in a newly created ArrayAdapter<Custom object>, which is also set to a ListView with lv.setAdapter(adapter). so far so good!

now the thing is: back in the MainActivity I will need that adapter again, cause I wanna add new items to it by calling adapter.add(items). for now I had the AsyncTask as an inner class of my MainActivity and could use the same ListView & the same ArrayAdapter, that worked very well!

but because I have another class which needs to execute that AsyncTask too, I changed that inner class AsyncTask to a standalone .java file (CustomAsyncTask.java)

-> now when I try to add new items to the ArrayAdapter it throws a NullPointerException! of course that is, cause the ArrayAdapter belongs to the AsyncTask and is created there so I tried to give the ListView and the ArrayAdapter from the MainActivity as a parameter for the CustomAsyncTask constructor to use it in there but that did not work, the ArrayAdapter in MainActivity is always null causing the Exception

any ideas how to solve that? I would really appreciate it.

here the code of the MainActivity.java:

// global variables
ArrayAdapter<Custom object> arrayadapter;
ListView listview;
ProgressBar progressbar;

...

protected void myMethod() {
    CustomAsyncTask hTask = new CustomAsyncTask(this, listview, progressbar, arrayadapter);
    hTaskPlaylist.execute(String sth);
}

...

protected void anotherMethod() {
    arrayadapter.add(item);
}

and the code of CustomAsyncTask.java:

package com.mypackage.test;

import java.util.ArrayList;

import android.content.Context;
import android.os.AsyncTask;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;

public class CustomAsyncTask extends AsyncTask<String, Void, ArrayList<Custom object>>{

    Context context;
    ListView listview;
    ProgressBar progressbar;
    ArrayAdapter<Custom object> arrayadapter;

    public CustomAsyncTask(Context con, ListView lv, ProgressBar pb, ArrayAdapter<Custom object> aa) {
        this.context = con;
        this.listview = lv;
        this.progressbar = pb;
        this.arrayadapter = aa;
    }

    @Override
    protected void onPreExecute() {
        listview.setVisibility(ListView.GONE);
        progressbar.setVisibility(ProgressBar.VISIBLE);
        super.onPreExecute();
    }

    @Override
    protected ArrayList<Custom object> doInBackground(String... params) {
            ArrayList<Custom object> list = new ArrayList<Custom object>();

            ... doing something and populating list
            return list;
    }

    @Override
    protected void onPostExecute(ArrayList<Custom object> list) {
        super.onPostExecute(list);

        arrayadapter = new ArrayAdapter<Custom object>(context, android.R.layout.simple_list_item_1, list);
        listview.setAdapter(arrayadapter);

        progressbar.setVisibility(ProgressBar.GONE);
                listview.setVisibility(ListView.VISIBLE);
    }

    }
}

Upvotes: 1

Views: 2711

Answers (2)

user1515520
user1515520

Reputation: 634

Now I tried that and pass the MainActivity as a parameter instead of the Context, here is what I changed:

public class CustomAsyncTask extends AsyncTask<String, Void, ArrayList<Custom object>>{

    **MainActivity activity**;
    ListView listview;
    ProgressBar progressbar;
    ArrayAdapter<Custom object> arrayadapter;

    public CustomAsyncTask(**MainActivity act**, ListView lv, ProgressBar pb, ArrayAdapter<Custom object> aa) {
        **this.activity = act;**
        this.listview = lv;
        this.progressbar = pb;
        this.arrayadapter = aa;
    }

    ...

    @Override
    protected void onPostExecute(ArrayList<Custom object> list) {
        super.onPostExecute(list);

        arrayadapter = new ArrayAdapter<Custom object>(context, android.R.layout.simple_list_item_1, list);
        listview.setAdapter(arrayadapter);
        **activity.arrayadapter = arrayadapter;**

        progressbar.setVisibility(ProgressBar.GONE);
        listview.setVisibility(ListView.VISIBLE);
    }

}

Yeah, it worked! Thank you Joel, but I'm still wondering why I can pass listview from MainActivity, call a function on that listview in AsyncTask and normally work with that listview back in MainActivity, any ideas?

And another question: is it right, that the only difference in passing an Activity object instead of a Context object, is you're having access to the available variables and methods you defined in your Activity?

Upvotes: 0

Joel
Joel

Reputation: 4772

You could make your ArrayAdapter static.. Then anytime you want to access it you can simply say CustomAsyncTask.arrayadapter.add(items); You are also allowed to add your own functions to your custom asynctask class. You could create something like public ArrayAdapter<> getAdapter(). But careful, you are going to have multiple threads accessing/changing that object regardless, so it would be a good idea to synchronize access.

You could try something like this...

ArrayAdapter globalAdapter;
globalAdapter = new CustomAsyncTask().execute(/*your parameters here*/).get();

Upvotes: 1

Related Questions