Search code examples
androidandroid-asynctaskaquery

Using AQuery with Android


I need to use AQuery in my Android project, in order to do asynchronous calls to the server. I just want to call the server and when it will give me data, I'll update my view with these data. So, I wrote the asynchronous call inside an AsyncTask. Below you can see what I did:

public class Tab1Fragment extends Fragment implements OnItemClickListener {

    private ListView categorieListView ; 

    private ArrayAdapter<String> listAdapterCategorie ;
    private AQuery aq;
    private String[] lista = null;
    private ProgressDialog pDialog;
    private String nome_categoria;
    private int[] arrayID = null;

    ArrayList<String> planetList;
    JsonRequestActivity categoryAjax;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        pDialog = new ProgressDialog(getActivity());
        LinearLayout view = (LinearLayout) inflater.inflate(R.layout.tab1, container, false);
        aq = new AQuery(this.getActivity(), view);                       
        categorieListView = (ListView) view.findViewById(R.id.listView1);        
        //new FetchMyDataTask(this.getActivity(), new FetchMyDataTaskCompleteListener(listAdapterCategorie, categorieListView, this.getActivity()), aq).execute("InputString");

        if(lista == null){
            new AggiornaLista().execute();
        }else{
            listAdapterCategorie = new ArrayAdapter<String>(getActivity().getApplicationContext(), R.layout.categoriegenerali, R.id.nomeAttivita, lista);
            categorieListView.setAdapter( listAdapterCategorie );
        }

        categorieListView.setOnItemClickListener(this);
        return view;
    }


    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {

        Intent esercizioScelto = new Intent(this.getActivity(), CategoriaScelta.class);
        nome_categoria = categorieListView.getItemAtPosition(position).toString();
        esercizioScelto.putExtra("nome_categoria", nome_categoria);
        esercizioScelto.putExtra("id_categoria", arrayID[position]);
        startActivity(esercizioScelto);   
    }             

    private class AggiornaLista extends AsyncTask<String, Void, String[]>{
        @Override
        protected void onPreExecute(){
            super.onPreExecute();
            pDialog.setMessage("Caricamento dati server");                  
        }

        @Override
        protected String[] doInBackground(String... params) {
            String url = Const.URL_JSON_ARRAY;

            Map<String, String> params2 = new HashMap<String, String>();
            params2.put("type", "get_all");

            aq.ajax(url, params2, JSONArray.class, new AjaxCallback<JSONArray>() {                                                

                @Override
                public void callback(String url, JSONArray json, AjaxStatus status) {
                    if(json != null){
                        lista = new String[json.length()];
                        arrayID = new int[json.length()];
                        for(int i = 0; i < json.length(); i++){
                            try {
                                lista[i] = result.getJSONObject(i).getString("Name");
                                arrayID[i] = result.getJSONObject(i).getInt("ID");
                            } 
                            catch (JSONException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                        //Toast.makeText(aq.getContext(), jsonArray.toString(), Toast.LENGTH_LONG).show();
                    }else{                              
                        //ajax error, show error code
                        //Toast.makeText(aq.getContext(), "Error:" + status.getCode(), Toast.LENGTH_LONG).show();
                    }
                    // do something with the result                             

                }
            });       
            return lista;
        }

        @Override
        protected void onPostExecute(String result[])
        {
            super.onPostExecute(result);
            pDialog.dismiss();
            listAdapterCategorie = new ArrayAdapter<String>(getActivity().getApplicationContext(), R.layout.categoriegenerali, R.id.nomeAttivita, result);

            // Set the ArrayAdapter as the ListView's adapter. 
            categorieListView.setAdapter( listAdapterCategorie );

        }

    }

}

That implentation does not work as I expected. In fact, inside the onPostExecute, the parameter returned by the doInBackground is not updated and it contains the initialization value (null). Then I changed something only in the AsyncTask:

private class AggiornaLista extends AsyncTask<String, Void, Void>
    {
        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
            pDialog.setMessage("Caricamento dati server");

        }

        @Override
        protected Void doInBackground(String... params) {
            String url = Const.URL_JSON_ARRAY;

            Map<String, String> params2 = new HashMap<String, String>();
            params2.put("type", "get_all");

            aq.ajax(url, params2, JSONArray.class, new AjaxCallback<JSONArray>() {                                                
                @Override
                public void callback(String url, JSONArray json, AjaxStatus status) {
                    if(json != null){
                        lista = new String[json.length()];
                        arrayID = new int[json.length()];
                        for(int i = 0; i < json.length(); i++){
                            try {
                                lista[i] = result.getJSONObject(i).getString("Name");
                                arrayID[i] = result.getJSONObject(i).getInt("ID");
                            } catch (JSONException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                        //Toast.makeText(aq.getContext(), jsonArray.toString(), Toast.LENGTH_LONG).show();
                    }else{                              
                        //ajax error, show error code
                        //Toast.makeText(aq.getContext(), "Error:" + status.getCode(), Toast.LENGTH_LONG).show();
                    }
                    // do something with the result                             
                    listAdapterCategorie = new ArrayAdapter<String>(getActivity().getApplicationContext(), R.layout.categoriegenerali, R.id.nomeAttivita, lista);

                    // Set the ArrayAdapter as the ListView's adapter. 
                    categorieListView.setAdapter( listAdapterCategorie );
                }
            });       
            return null;
        }

        @Override
        protected void onPostExecute(Void result)
        {
            super.onPostExecute(result);
            pDialog.dismiss();
        }

    }

Doing that, the user inteface is correctly updated, but I think it's not the correct way to do that. So, what can I do? Thanks.

Andrea


Solution

  • If I am not mistaken you are currently wrapping an asynchronous task in an asynchronous task. Your aq.ajax(...) is starting a new thread to make the call and then invokes the callback(...) you defined. The AsyncTask executes the doInBackground(), where you start another task. The doInBackground() method finishes, before your ajax call is done. So the onPostExecute() is executed before the ajax call is finished.

    The solution would be to omit the whole AsyncTask structure. Just call your aq.ajax() in your main onCreateView and do what you have to do, when the call returns in the callback you defined. (Basically put the contents of your doInBackGround() in your main