Mike
Mike

Reputation: 6839

Executing Async tasks in fragments

I am attempting to execute an async task in a fragment after converting my activities into fragments. When I call my async task from the activity I have to pass 'this' with it in order to allow the async task to change text and things after it receives the information. I am a bit confused on how to do this all with fragments. Here is what I got so far:

I execute the asynck task with:

new GetYourTopTasteBeers(this).execute(url);

the code for the async task is:

public class GetYourTopTasteBeers extends AsyncTask<String, Void, String> {

    Context c;
    private ProgressDialog Dialog;

    public GetYourTopTasteBeers (Context context)
    {
        c = context;
        Dialog = new ProgressDialog(c);
    }

    @Override
    protected String doInBackground(String... arg0) {
        // TODO Auto-generated method stub
        return readJSONFeed(arg0[0]);
    }

    protected void onPreExecute() {
        Dialog.setMessage("Getting beers");

        Dialog.setTitle("Loading");
        Dialog.setCancelable(false);
        Dialog.show();
    }

    protected void onPostExecute(String result){
        //decode json here
        try{
            JSONArray jsonArray = new JSONArray(result);


            //acces listview
            ListView lv = (ListView) ((Activity) c).findViewById(R.id.topTasteBeers);

            //make array list for beer
            final List<ShortBeerInfo> tasteList = new ArrayList<ShortBeerInfo>();



            for(int i = 0; i < jsonArray.length(); i++) {

                String beer = jsonArray.getJSONObject(i).getString("beer");
                String rate = jsonArray.getJSONObject(i).getString("rate");
                String beerID = jsonArray.getJSONObject(i).getString("id");
                String breweryID = jsonArray.getJSONObject(i).getString("breweryID");


                int count = i + 1;

                beer = count + ". " + beer;


                //create object
                ShortBeerInfo tempTaste = new ShortBeerInfo(beer, rate, beerID , breweryID);

                //add to arraylist
                tasteList.add(tempTaste);


                //add items to listview
                ShortBeerInfoAdapter adapter1 = new ShortBeerInfoAdapter(c ,R.layout.brewer_stats_listview, tasteList);
                lv.setAdapter(adapter1);

                //set up clicks
                lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> arg0, View arg1,
                                            int arg2, long arg3) {
                        ShortBeerInfo o=(ShortBeerInfo)arg0.getItemAtPosition(arg2);

                        String tempID = o.id;
                        String tempBrewID = o.brewery;

                        Toast toast = Toast.makeText(c, tempID, Toast.LENGTH_SHORT);
                        toast.show();

                        //todo: change fragment to beer page

                        Intent myIntent = new Intent(c, BeerPage2.class);
                        myIntent.putExtra("id", tempID);
                        myIntent.putExtra("breweryID", tempBrewID);
                        c.startActivity(myIntent);


                    }
                });




            }

        }
        catch(Exception e){

        }

        Dialog.dismiss();

    }

    public String readJSONFeed(String URL) {
        StringBuilder stringBuilder = new StringBuilder();
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(URL);
        try {
            HttpResponse response = httpClient.execute(httpGet);
            StatusLine statusLine = response.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            if (statusCode == 200) {
                HttpEntity entity = response.getEntity();
                InputStream inputStream = entity.getContent();
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(inputStream));
                String line;
                while ((line = reader.readLine()) != null) {
                    stringBuilder.append(line);
                }
                inputStream.close();
            } else {
                Log.d("JSON", "Failed to download file");
            }
        } catch (Exception e) {
            Log.d("readJSONFeed", e.getLocalizedMessage());
        }
        return stringBuilder.toString();
    }

}

My problem is that I can not pass 'this' from a fragment...

Bonus Question:

Also as you can see I am not done converting my code for the fragments. I need to change this to load a fragment instead of change activity:

//todo: change fragment to beer page
                        Intent myIntent = new Intent(c, BeerPage2.class);
                        myIntent.putExtra("id", tempID);
                        myIntent.putExtra("breweryID", tempBrewID);
                        c.startActivity(myIntent);

HOw can I pass values between fragments like I am doing between activities in that above code?

Upvotes: 0

Views: 3508

Answers (2)

nKn
nKn

Reputation: 13761

Since Fragments don't admit this, you may call getActivity() instead which will provide the context you need to execute the AsyncTask.

Be careful, though, as running an AsyncTask within a Fragment may lead to return a result to the caller Activity that has already been destroyed at the time your AsyncTask concluded its process. It's necessary to take additional precautions, and always check whether the Fragment hasn't already been destroyed. This can be done using this.isAdded() in your Fragment.

A good practice is to cancel your AsyncTask in the onStop() and onPause() methods. That will make the onPostExecute() not execute code if the Fragment is not active anymore (getActivity() would return null).

Upvotes: 2

Egor Neliuba
Egor Neliuba

Reputation: 15054

You cannot pass this because in this situation this referrers to your fragment, which doesn't extend Context. But you need Context (your GetYourTopTasteBeers takes Context as a parameter):

public GetYourTopTasteBeers (Context context)

Instead, pass your Activity like so:

new GetYourTopTasteBeers(getActivity()).execute(url);

Upvotes: 1

Related Questions