trying to launch a fragment from an async task - android

I have an async task which is called for a fragment and populates a listview. When I try and set the OnClick for the listview I get an error in my code for setting the fragment to load based on the listview item clicked:
FragmentManager man= getFragmentManager();
FragmentTransaction tran=man.beginTransaction();
Fragment_one = new StylePage2();
final Bundle bundle = new Bundle();
bundle.putString("beerIDSent", bID);
Fragment_one.setArguments(bundle);
tran.replace(R.id.main, Fragment_one);//tran.
tran.addToBackStack(null);
tran.commit();
The error shows for the line:
FragmentManager man= getFragmentManager();
The error is, can not resolve method getFragmentManager()
I am assuming you can only access that method from within a fragment, so I am a bit lost on how to launch it from something that extends asynctask.
The full code for the async task is below:
public class GetStyleStatisticsJSON extends AsyncTask<String, Void, String> {
Context c;
private ProgressDialog Dialog;
android.support.v4.app.Fragment Fragment_one;
public GetStyleStatisticsJSON(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("Analyzing Statistics");
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.yourStyleStatistics);
//make array list for beer
final List<StyleInfo> tasteList = new ArrayList<StyleInfo>();
for(int i = 0; i < jsonArray.length(); i++) {
String style = jsonArray.getJSONObject(i).getString("style");
String rate = jsonArray.getJSONObject(i).getString("rate");
String beerID = jsonArray.getJSONObject(i).getString("id");
int count = i + 1;
style = count + ". " + style;
//create object
StyleInfo tempTaste = new StyleInfo(style, rate, beerID);
//add to arraylist
tasteList.add(tempTaste);
//add items to listview
StyleInfoAdapter adapter1 = new StyleInfoAdapter(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) {
StyleInfo o=(StyleInfo)arg0.getItemAtPosition(arg2);
String bID = o.id;
//todo: add onclick for fragment to load
FragmentManager man= getFragmentManager();
FragmentTransaction tran=man.beginTransaction();
Fragment_one = new StylePage2();
final Bundle bundle = new Bundle();
bundle.putString("beerIDSent", bID);
Fragment_one.setArguments(bundle);
tran.replace(R.id.main, Fragment_one);//tran.
tran.addToBackStack(null);
tran.commit();
}
});
}
}
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();
}
}
UPDATE
I tried changing it to this:
FragmentManager man = ((Activity) c).getFragmentManager();
BUt I am getting this error:
Incompatible types.
Required:
android.support.v4.app.FragmentManager
Found:
android.app.FragmentManager
Update 2
I just tried this:
FragmentManager man= MainDraw.getFragmentManager();
and get this error:
Non-static method 'getFragmentManager()' cannot be referenced from a static context

It is very good practice to always create fragments from the holding activity only, so in this case what you would do is create a callback (interface) in your onclick to your activity that would create the fragment just like you would if you needed to communicate with your activity from your fragment.
doing this will fix your problem because Activity has getFragmentManager()
EDIT
OnArticleSelectedListener listener;
public interface OnArticleSelectedListener{
public void onArticleSelected(/*whatever you want to pass in it*/);
}
in your GetStyleStatisticsJSON create a method that sets the listener
public void setOnArticleSelectedListener(OnArticleSelectedListener listener){
this.listener = listener;
}
then in your onClick just call it
listener.onArticleSelected();
then declare your asynctask like this
GetStyleStatisticsJSON task = new GetStyleStatisticsJSON(getActvity());
task.setOnArticleSelectedListener(new OnArticleSelectedListener(){
#Override
public void onArticleSelected(){
}
});
task.execute(url)

Using
FragmentManager man= YourActivity.getFragmentManager();
instead of
FragmentManager man= getFragmentManager();

Related

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?
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).
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);

Force close when new fragment with async task is launched

I have a button that loads a new fragment but it is force closing with this error:
java.lang.NullPointerException
at com.beerportfolio.beerportfoliopro.BPTopTastes.onCreateView(BPTopTastes.java:29)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1500)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:5789)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:843)
at dalvik.system.NativeStart.main(Native Method)
the button that loads the new fragment is this:
public class Discover extends Fragment {
Fragment Fragment_one;
Fragment Fragment_two;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_discover, container, false);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
String userName = prefs.getString("userName", null);
String userID = prefs.getString("userID", null);
//add button onclick fo top beers
Button bt = (Button)v.findViewById(R.id.discoverBeers);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// do whatever stuff you wanna do here
FragmentManager man=getFragmentManager();
FragmentTransaction tran=man.beginTransaction();
Fragment_one=new BPTopBeers();
tran.replace(R.id.main, Fragment_one);//tran.
tran.addToBackStack(null);
tran.commit();
}
});
//todo: add button onclick fo top tastes
Button bt2 = (Button)v.findViewById(R.id.discoverTaste);
bt2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// do whatever stuff you wanna do here
FragmentManager man=getFragmentManager();
FragmentTransaction tran=man.beginTransaction();
Fragment_two=new BPTopTastes();
tran.replace(R.id.main, Fragment_two);//tran.
tran.addToBackStack(null);
tran.commit();
}
});
// Inflate the layout for this fragment
//todo: change to discover layout
return v;
}
the fragment that is being launched is:
public class BPTopTastes extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.taste_statistics_layout, container, false);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
String userName = prefs.getString("userName", null);
String userID = prefs.getString("userID", null);
String title = "Top Tastes on Beer Portfolio";
TextView topTitle = (TextView) v.findViewById(R.id.topTasteTitle);
topTitle.setText(title);
//construct url
String url = "myURL";
//async task goes here
new GetTasteStatisticsJSON(getActivity()).execute(url);
// Inflate the layout for this fragment
return v;
}
}
and the async task which is being called is:
public class GetTasteStatisticsJSON extends AsyncTask<String, Void, String> {
Context c;
private ProgressDialog Dialog;
public GetTasteStatisticsJSON(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 tastes");
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.yourTasteStatistics);
//make array list for beer
final List<TasteInfo> tasteList = new ArrayList<TasteInfo>();
for(int i = 0; i < jsonArray.length(); i++) {
String style = jsonArray.getJSONObject(i).getString("taste");
String rate = jsonArray.getJSONObject(i).getString("rate");
int count = i + 1;
style = count + ". " + style;
Log.d("brewery stats", style);
//create object
TasteInfo tempTaste = new TasteInfo(style, rate);
//add to arraylist
tasteList.add(tempTaste);
//add items to listview
TasteInfoAdapter adapter1 = new TasteInfoAdapter(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) {
TasteInfo o=(TasteInfo)arg0.getItemAtPosition(arg2);
String tempTaste = o.taste;
//todo: load taste page fragment
//Intent myIntent = new Intent(c, TastePage.class);
// myIntent.putExtra("taste", tempTaste);
//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();
}
}
I am a bit confused cause I have another button in the same fragment that launches a new fragment in a similar way just fine...
I just noticed my mistake after combing through my code. I have the wrong id here in this line:
TextView topTitle = (TextView) v.findViewById(R.id.topTasteTitle);
so it could not find that, to set the title.
Can you check the BPTopTastes layout is inflating correctly, and hence topTitle is not null when you call the setText() method on it.
Does it work when you remove the async task ?
The Eclipse debugger can be set to halt on exception which might give you some pointers.

Fragment not being replaced, be placed on top of other fragment

I am slowly converting my app to fragments vs activities, and I am getting some odd behavior at the moment. I have a button that when pressed should load a new fragment into view then execute an async task in order to load information into the fragment.
My code for the fragment which contains the button to swap the new fragment is:
public class Discover extends Fragment {
Fragment Fragment_one;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_discover, container, false);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
String userName = prefs.getString("userName", null);
String userID = prefs.getString("userID", null);
//add button onclick programatically
Button bt = (Button)v.findViewById(R.id.discoverBeers);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// do whatever stuff you wanna do here
FragmentManager man=getFragmentManager();
FragmentTransaction tran=man.beginTransaction();
Fragment_one=new BPTopBeers();
tran.add(R.id.main, Fragment_one);//tran.
tran.addToBackStack(null);
tran.commit();
}
});
// Inflate the layout for this fragment
//todo: change to discover layout
return v;
}
I know it loading on top of the other fragment and not swapping because I can see the other fragment below it:
The fragment that is loaded on the button click is:
public class BPTopBeers extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.toptaste_layout, container, false);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
String userName = prefs.getString("userName", null);
String userID = prefs.getString("userID", null);
String title = "Top Beers on Beer Portfolio";
TextView topTitle = (TextView) v.findViewById(R.id.topTasteTitle);
topTitle.setText(title);
//construct url
String url = "myURL";
Log.d("myUrl", url);
//async task goes here
new GetYourTopTasteBeers(getActivity()).execute(url);
// Inflate the layout for this fragment
return v;
}
and the async task which is called in that fragment looks like this:
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();
}
}
When you use add it just straight add the fragment to the view however when you use replace it removes the current fragment then adds the new one which is what you are looking for since it appears your XML is not set to match_parent
You can hide old fragment,if you want to back to previous
fragmentManager
.beginTransaction()
.hide(previous fragment)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.add(R.id.content_frame, newFragment,
ParserConstants.FRAGMENT_MAIN).addToBackStack(null)
.commitAllowingStateLoss();

Android Fragment - SlidingMenu - ListActivity

So I have the slidingmenu(jfeinstein10) library added to my project and the menu working. The problem I have run into is based on my app extends ListActivity.
I have seen a couple questions about this and most suggest extending to Fragment to get Fragments working for the menu. I wanted to know if there was a way to not use Fragments to get the menu list to work.
Every time I move to SlidingFragmentActivity or any other Fragment Activity, onListItemClick and other methods start breaking.
Below is my code:
public class MainListActivity extends ListActivity {
public static final int NUMBER_OF_POSTS = 20;
public static final String TAG = MainListActivity.class.getSimpleName();
protected JSONObject mBlogData;
protected ProgressBar mProgressBar;
private SlidingMenu menu;
static final String KEY_TITLE = "title";
static final String KEY_AUTHOR = "author";
static final String KEY_IMAGE = "image";
ListView list;
LazyAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//setBehindContentView(R.layout.menu_frame);
mProgressBar = (ProgressBar) findViewById(R.id.progressBar1);
menu = new SlidingMenu(this);
menu.setMode(SlidingMenu.LEFT);
menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
menu.setShadowWidth(5);
menu.setFadeDegree(0.35f);
menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
menu.setBehindWidth(R.dimen.shadow_width);
menu.setShadowDrawable(R.drawable.shadow);
menu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
menu.setMenu(R.layout.menu_frame);
//getFragmentManager().beginTransaction().replace(R.id.menu_frame, new MenuFragment()).commit();
if(isNetworkAvailable()){
GetBlogPostsTask getBlogPostsTask = new GetBlogPostsTask();
mProgressBar.setVisibility(View.VISIBLE);
getBlogPostsTask.execute();
}else{
Toast.makeText(this, "Network is unavailable", Toast.LENGTH_LONG).show();
}
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id){
super.onListItemClick(l, v, position, id);
try{
JSONArray jsonPosts = mBlogData.getJSONArray("items");
JSONObject jsonPost = jsonPosts.getJSONObject(position);
String blogSummary = jsonPost.getString("summary");
String blogUrl = jsonPost.getString("bitly");
Intent intent = new Intent(this, BlogWebViewActivity.class);
intent.setData(Uri.parse(blogSummary));
intent.putExtra("mUrl",blogUrl);
startActivity(intent);
}catch(JSONException e){
logException(e);
}
}
private void logException(Exception e) {
Log.e(TAG, "Exception caught!", e);
}
private boolean isNetworkAvailable() {
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if(networkInfo != null && networkInfo.isConnected()){
isAvailable = true;
}
return isAvailable;
}
public void handleBlogResponse() {
mProgressBar.setVisibility(View.INVISIBLE);
if(mBlogData == null){
updateDisplayForError();
}else{
try {
JSONArray jsonPosts = mBlogData.getJSONArray("items");
ArrayList<HashMap<String,String>> blogPosts = new ArrayList<HashMap<String,String>>();
for (int i=0;i<jsonPosts.length();i++){
JSONObject post = jsonPosts.getJSONObject(i);
String title = post.getString(KEY_TITLE);
title = Html.fromHtml(title).toString();
String tag = post.getString(KEY_AUTHOR);
tag = Html.fromHtml(tag).toString();
String image = post.getString(KEY_IMAGE);
image = Html.fromHtml(image).toString();
HashMap<String, String> blogPost = new HashMap<String,String>();
blogPost.put(KEY_TITLE, title);
blogPost.put(KEY_AUTHOR, tag);;
blogPost.put(KEY_IMAGE, image);
blogPosts.add(blogPost);
}
list=getListView();
LazyAdapter adapter = new LazyAdapter(this, blogPosts);
list.setAdapter(adapter);
} catch (JSONException e) {
logException(e);
}
}
}
private void updateDisplayForError() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.error_title));
builder.setMessage(getString(R.string.error_message));
builder.setPositiveButton(android.R.string.ok,null);
AlertDialog dialog = builder.create();
dialog.show();
TextView emptyTextView = (TextView) getListView().getEmptyView();
emptyTextView.setText(getString(R.string.no_items));
}
private class GetBlogPostsTask extends AsyncTask<Object, Void, JSONObject>{
#Override
protected JSONObject doInBackground(Object... params) {
int responseCode = -1;
JSONObject jsonResponse = null;
StringBuilder builder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://www.domain.com/app_json.js");
try {
HttpResponse response = client.execute(httpget);
StatusLine statusLine = response.getStatusLine();
responseCode = statusLine.getStatusCode();
if(responseCode == HttpURLConnection.HTTP_OK){
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String line;
while((line = reader.readLine()) != null){
builder.append(line);
}
jsonResponse = new JSONObject(builder.toString());
}else{
Log.i(TAG, "HTTP Failed: "+responseCode);
}
} catch (MalformedURLException e) {
logException(e);
} catch (IOException e) {
logException(e);
}
catch(Exception e){
logException(e);
}
return jsonResponse;
}
#Override
protected void onPostExecute(JSONObject result){
mBlogData = result;
handleBlogResponse();
}
}
#Override
public void onBackPressed() {
if (menu.isMenuShowing()) {
menu.showContent();
} else {
super.onBackPressed();
}
}
}
I have the menu items stored in /values/array.xml as a string-array.
I have setup a fragment as well, but dont know how to access it without extending to Fragment from ListActivity.
Below is my Fragment based on the example fragments from github:
public class MenuFragment extends ListFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.menu_list, null);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String[] colors = getResources().getStringArray(R.array.menu_items);
ArrayAdapter<String> colorAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, android.R.id.text1, colors);
setListAdapter(colorAdapter);
}
#Override
public void onListItemClick(ListView lv, View v, int position, long id) {
Fragment newContent = null;
switch (position) {
case 0:
//newContent = new ColorFragment(R.color.red);
break;
case 1:
//newContent = new ColorFragment(R.color.green);
break;
case 2:
//newContent = new ColorFragment(R.color.blue);
break;
case 3:
//newContent = new ColorFragment(android.R.color.white);
break;
case 4:
//newContent = new ColorFragment(android.R.color.black);
break;
}
if (newContent != null)
switchFragment(newContent);
}
// the meat of switching the above fragment
private void switchFragment(Fragment fragment) {
if (getActivity() == null)
return;
}
}
Thanks

Android ListAdapter How to Correct: Cannot make a static reference to the non-static method

I'm trying to put some custom list adapters into their own classes to make my app have less redundant code and to make it more manageable.
I call on the different adapter classes thru a conditional statement within a ListFragment. I originally had the adapters in the ListFragment class and this all worked as planed. Now to clean up everything and to get all that code out of the ListFragment, I moved the Adapters out and into their own classes. Since that was done, these methods have to be static so I can call on them but these new classes now containa lot of:
Cannot make a static reference to the non-static method
setListAdapter(ListAdapter) from the type ListFragment
Specifically the setListAdapter, setListAdapter, getFragmentManager, and getFragmentManager methods. I don't want a ton of ListView Fragment classes and since a lot of code would be reused, It makes more since to only have one ListFragment and use conditionals to get the correct adapter but I don't know how to fix these new classes so I can use them.
Sorry for the long explanation. I'll try to only post the relevant code to get the idea to what I am trying to accomplish and for you to guide me.
Can this be done the way I am doing this and how do I correct it?
If there is a better way, please post some code with your explination or code in what needs to be changed within my Adapter Class.
In my fragment's onActivityCreated:
. . .
// Get the string to query from last Fragment and pass it to this
// Fragment
Bundle args = this.getArguments();
boolean rawRes = args.getBoolean(KEY_IS_RAW_RES);
String url = args.getString(KEY_URL);
int fileName = args.getInt(KEY_RES_FILE);
this.getJsonFile(url, rawRes, fileName);
}
public void getJsonFile(String url, boolean rawRes, int fileName) {
if (rawRes == true) {
getFromRawRes(fileName);
} else {
getFromURL(url);
}
}
public void getFromRawRes(int fileName) {
InputStream file = getResources().openRawResource(fileName);
JSONParser jParser = new JSONParser();
JSONArray json = jParser.getJSONFromRes(file);
ListAdapter_SevenItem.callback(json, context);//<--THIS IS A CALL TO THE ADAPTER!!
}
One of the Adapters:
public class ListAdapter_SevenItem extends ListViewFragment {
. . .
public static void callback(JSONArray json, Context c) {
if (json != null) {
// Hashmap for ListView
. . .
// create the list item mapping
String[] from = new String[]{TAG_LABEL, TAG_TITLE, TAG_DISCR, TAG_RES_FILE, TAG_IS_RAW_RES, TAG_CONT_ID};
int[] to = new int[]{R.id.listLabel, R.id.listTitle, R.id.listDiscription, R.id.listResFile, R.id.listIsRawRes, R.id.listContID};
// Updating parsed JSON data into ListView
SimpleAdapter adapter = new SimpleAdapter(c, mList, R.layout.list_item, from, to);
setListAdapter(adapter);
// selecting single ListView item
final ListView lv = setListAdapter();
// Launching new screen on Selecting Single ListItem
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
MainActivity.mLayout.toggleSidebar();
setHasOptionsMenu(true);
FragmentManager fm = getFragmentManager();
final FragmentTransaction lcFT = fm.beginTransaction();
lcFT.setCustomAnimations(R.anim.slide_in, R.anim.hyperspace_out, R.anim.hyperspace_in, R.anim.slide_out);
final Bundle args = new Bundle();
String resFile = ((TextView) view.findViewById(R.id.listResFile)).getText().toString();
int passResFile = getFragmentManager().getIdentifier(resFile, "raw", "com.andaero.app");
args.putInt("KEY_RES_FILE", passResFile);
boolean isRawRes = true;
args.putBoolean("KEY_IS_RAW_RES", isRawRes);
// Delayed to improve animations
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
ListViewFragment lvf = new ListViewFragment();
lcFT.replace(R.id.listContainer, lvf).commit();
lvf.setArguments(args);
}
}, 300);
}
});
}
}
}
You're overcomplicating things.
There should not be static method/calls like the one you use. It should be very simple. Within the list fragment's onActivityCreated(Bundle savedInstanceState) you create an instance of your list adapter, and set it as the adapter using the setListAdapter().
Check for TitlesFragment sample in the tutorial on fragments.
A ListView Fragment Class that can be reused thru-out an application.
I use jgilfelt's universal JasonArrayAdapter class that can be downloaded on GitHub. The class here below can be used over and over thru-out the application so its the only ListView class needed - Which means a reduction in redundant code/classes. Esp., if you have list views that require different attributes and/or layouts.
If your loading this ListViewFragment from another Fragment:
String uri = "http://www.xxxx/myjsonfile.json";//EXAMPLE IF FROM A URL
String uri = "json/myjsonfile.json";//EXAMPLE GETTING FROM YOUR ASSETS FOLDER
args.putString("KEY_URI", uri);
String adptrID = "#";//USED TO DETERMINE WHICH LAYOUT TO USE
args.putString("KEY_ADPTR_ID", adptrID);
ListViewFragment lvf = new ListViewFragment();
lcFT.replace(R.id.myContainer, lvf).commit();
lvf.setArguments(args);
If If your loading this ListViewFragment from within it's self, just add the appropriate items in your JSON files and get them into your setArguments(args) Bundle.
If you have any improvements/etc to the methods, feel free to add it to your comment/answer. I'm new to Android and learning as I go... Thnx
ListViewFragment Class:
public class ListViewFragment extends ListFragment implements OnItemClickListener {
. . .
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Bundle getArgs = this.getArguments();
String URI = getArgs.getString(KEY_URI);
. . .
new GetJSONTask().execute(URI);
}
class GetJSONTask extends AsyncTask<String, Integer, String> {
protected String doInBackground(String... arg0) {
String uri = arg0[0];
InputStream is = null;
if (uri.contains("http") == true) {// Get JSON from URL
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(uri);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
BufferedReader rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
while ((line = rd.readLine()) != null) {
json += line;
}
rd.close();
return json;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} else {//Get JSON from Assets
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
InputStream jsonFile = getActivity().getAssets().open(uri);
Reader reader = new BufferedReader(new InputStreamReader(jsonFile, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
jsonFile.close();
} catch (IOException e) {
e.printStackTrace();
}
json = writer.toString();
// return JSON String
return json;
}
}
#Override
protected void onPostExecute(String result) {
try {
showData(result);
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getActivity(), "something went wrong", Toast.LENGTH_SHORT).show();
}
}
}
private void showData(String json) throws JSONException {
JSONObject o = new JSONObject(json);
JSONArray data = o.getJSONArray("results");
Bundle getArgs = this.getArguments();
String adptrID = getArgs.getString(KEY_ADPTR_ID);
if (adptrID == "3") {//Adapter for 3 items
String[] from = new String[]{"label", "title", "description", "uri", "adapterID", "containerID"};
int[] to = new int[]{R.id.listLabel, R.id.listTitle, R.id.listDiscription, R.id.listURI, R.id.listAdapterID, R.id.listContID};
ListAdapter adapter = new JSONArrayAdapter(getActivity(), data, R.layout.list_item, from, to, null);
getListView().setOnItemClickListener(this);
getListView().setAdapter(adapter);
}
if (adptrID == "4") {//Adapter for 4 items - Get the idea?
. . .
} . . .//Additional Adapter can be added....
}
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Bundle args = new Bundle();
Bundle getArgs = this.getArguments();
String uri = ((TextView) view.findViewById(R.id.listURI)).getText().toString();
args.putString("KEY_URI", uri);
String adptrID = ((TextView) view.findViewById(R.id.listAdapterID)).getText().toString();
args.putString("KEY_ADPTR_ID", adptrID);
String contID = ((TextView) view.findViewById(R.id.listContID)).getText().toString();
args.putString("KEY_CONTAINER_ID", contID);
//Conditional to determine witch container to load the ListViewFragment(this)
if (containerID == "listContainer") {
lcFT.replace(R.id.listContainer, lvf).commit();
lvf.setArguments(args);
}
if (containerID == "someOtherContainer") {
lcFT.replace(R.id.discriptionListContainer, lvf).commit();
lvf.setArguments(args);
}. . .
}

Categories

Resources