Reputation: 6839
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
Reputation: 13761
Since Fragment
s 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
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