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
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