Trigger AsyncTask class exception

5

The class below is responsible for getting data from a WCF Rest service:

public class MyAsyncTaskGeneric<T> extends AsyncTask<String, Void, T>{

    private final Class<T> typeGeneric;         

    public MyAsyncTaskGeneric(Class<T> typeGeneric) {
        this.typeGeneric = typeGeneric;     
    }

    @Override
    protected T doInBackground(String... params) {      
        T result = null;        
        try {               
            RestTemplate restTemplate = new RestTemplate();
            restTemplate.getMessageConverters().add(new GsonHttpMessageConverter());
            result = restTemplate.getForObject(params[0], typeGeneric);
        } catch (Exception e) {
            Log.i("Teste", e.getMessage());         
        } 
        return result;
    }
}

It is consumed by business class:

public class CidadeBll {    

    public CidadeBll() {

    }

    public Cidade[] GetCidades(String url) throws Exception {
        Cidade[] result = null;
        try {
            MyAsyncTaskGeneric<Cidade[]> myAsync = new MyAsyncTaskGeneric<Cidade[]>(Cidade[].class);
            result = myAsync.execute(url + "/cidades").get();
        } catch (Exception e) {
            throw e;
        }
        return result;
    }
}

Which in turn is consumed by an Activity:

btnGetCidades.setOnClickListener(new View.OnClickListener() {           
        @Override
        public void onClick(View v) {
            try {
                CidadeBll cidadeBll = new CidadeBll();
                Cidade[] cidades = cidadeBll.GetCidades(url2);

                if (cidades.length > 0){
                    Toast.makeText(getApplicationContext(), "Qtde de Cidades: " + cidades.length, Toast.LENGTH_LONG).show();
                }

            } catch (Exception e) {
                Toast.makeText(getApplicationContext(), "Erro:" + e.getMessage(), Toast.LENGTH_LONG).show();
            }
        }
    });

Considering possible exceptions triggered by WCF Rest, I would like the AsyncTask class to trigger the exception for the business class, and the business exception for Activity.

Is this possible?

    
asked by anonymous 10.04.2015 / 21:57

1 answer

4

Yes, it is possible. But first, I wanted to point out that you are making a design error: AsyncTask is intrinsically linked to the UI, so the onPreExecute() , onProgressUpdate(Progress...) , and onPostExecute(Result) methods have access to the UI Thread (see The 4 steps ). Therefore, you do not have to create Toast s in Activity , but in AsyncTask itself. So in Activity you instantiate a AsyncTask and in AsyncTask you instantiate a business class object to perform the job in the background.

Returning to your question: You can add an attribute of type Exception to your instance of AsyncTask and check the result in onPostExecute(Result) method. Here is an example code:

Activity with AsyncTask :

    btnGetCidades.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            new AsyncTask<String, Void, Cidade[]>() {

                // atributo que guarda excecao lancada
                private Exception e;

                @Override
                protected Cidade[] doInBackground(String... params) {
                    // em background
                    Cidade[] cidades = null;

                    try {
                        CidadeBll cidadeBll = new CidadeBll();
                        cidades = cidadeBll.GetCidades(params + "/cidades");
                    } catch (Exception e) {
                        this.e = e;
                        return null;
                    }

                    return cidades;
                }

                @Override
                protected void onPostExecute(Cidade[] cidades) {
                    // acesso a UI thread
                    if (cidades == null && e != null) {
                        // erro
                        Toast.makeText(
                                getApplicationContext(),
                                "Erro:" + e.getMessage(),
                                Toast.LENGTH_LONG).show();
                    } else {
                        // ok ..
                        if (cidades.length > 0){
                            Toast.makeText(
                                    getApplicationContext(),
                                    "Qtde de Cidades: " + cidades.length,
                                    Toast.LENGTH_LONG).show();
                        }
                    }
                }
            }.execute(url2);
        }
    });

CidadeBll.java (business class):

    public class CidadeBll {

        public CidadeBll() {

        }

        public Cidade[] GetCidades(String ... params) throws Exception {
            Cidade[] result = null;

            try {
                RestTemplate restTemplate = new RestTemplate();
                restTemplate.getMessageConverters().add(new GsonHttpMessageConverter());
                result = restTemplate.getForObject(params[0], Cidade[].class);
            } catch (Exception e) {
                Log.i("Teste", e.getMessage());

                throw e;
            }

            return result;
        }
    }

In case the Acivity code has become large / confusing, it can be used in another class, but please allow the UI modify logic from the AsyncTask methods that have access to the UI Thread. / p>

I hope I have helped and for more information on how it works AsyncTask see the documentation .

    
07.05.2015 / 06:08