Filling a spinner from JSON web data The code below is used to download a JSON data from the web and use the data to fill a spinner. I would like to know if there is better way. Is it wise to move everything from onGetPriceType to the AsyncTask?

Interface

public interface GetBuildTypeInterface {
    public void onGetBuildType(HashMap&lt;String,String&gt; result);
}


AsyncTask

public class GetBuildType extends AsyncTask&lt;Void, Void, JSONArray&gt; {
    private GetBuildTypeInterface callback;

    public GetBuildType(GetBuildTypeInterface callback) {
        this.callback = callback;
    }

    @Override
    protected JSONArray doInBackground(Void... params) {
        UserFunctions u = new UserFunctions();
        return u.getBt();
    }

    @Override
    protected void onPostExecute(JSONArray result) {
        super.onPostExecute(result);
        HashMap&lt;String, String&gt; map = new HashMap&lt;String, String&gt;();

        if (result != null) {
            map = result.parse();
            callback.onGetBuildType(map);

        } else {
            callback.onGetBuildType(null);
        }
    }
}


Activity

public class AddFillActivityApp extends ErrorActivity implements
        GetBuildTypeInterface

{
    ArrayAdapter&lt;String&gt; adapterBuild;
    Spinner spinBuildType;

@Override
    public void onGetPriceType(final HashMap&lt;String, String&gt; result) {
        if (result != null) {
            List&lt;String&gt; fields = new ArrayList&lt;String&gt;();
            fields.addAll(result.keySet());
            adapterPrice = new ArrayAdapter&lt;String&gt;(this,
                    android.R.layout.simple_spinner_item, fields);
            adapterPrice
                    .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spinPriceType.setAdapter(adapterPrice);

            spinPriceType
                    .setOnItemSelectedListener(new OnItemSelectedListener() {
                        @Override
                        public void onItemSelected(AdapterView&lt;?&gt; parent,
                                View view, int position, long id) {

                            if (position &gt; -1) {
                                String selection = spinPriceType
                                        .getSelectedItem().toString();
                                a.setNot_priceFor(result.get(selection));
                            }   
                        }

                        @Override
                        public void onNothingSelected(AdapterView&lt;?&gt; arg0) {    
                        }
                    });
        }else error();
    }
}
I see a very big advantage of your current approach rather than moving the implementation of onGetPriceType to the GetBuildType class (May I suggest changing the name to GetBuildTypeTask?)


Decoupling code. Your GetBuildType class is 100% independent of your activity. That is a good sign. If needed, you could at any time re-use the GetBuildType class and provide it with another GetBuildTypeInterface.


A side suggestion: I assume that result.parse() doesn't need to be run on the UI-thread, so you can change your class to extend AsyncTask&lt;Void, Void, Map&lt;String, String&gt;&gt; and make the conversion to map in doInBackground (or return null if u.getBt() returns null). Also, you don't need to create a new empty HashMap before parsing the JsonArray, simply Map&lt;String, String&gt; map = jsonArray.parse(); will do.

The only disadvantage I see with your current implementation is that you get an extra interface. But I really don't think that's so bad compared to having decoupled code.