Force close when new fragment with async task is launched - android

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.

Related

Android Populate Listview from JSON (link from edittext)

I am new in android and am working with a project that loads data from internet into listview. I got my prototype here: kaleidosblog.com/android-listview-load-data-from-json
So these will be the json links:
http://www.funtrial.com/christiancepe/announcements/json.php?page=1
http://www.funtrial.com/christiancepe/announcements/json.php?page=2
So on..
In my activity, I have my EditText, Button and ListView.
Editext will get the url.
Button will be use to load the json link (from url) to listview
Listview will display datas
In my current program, it only works on first click of button. So once I entered the first json, it will show the correct data. But when I try to change the json on EditText, still the ListView is populated by the first json. In short, my ListView does not refresh everytime I am changing the link and clicking the button.
What's wrong with this?
Main Activity:
protected void onCreate(Bundle savedInstanceState) {
final Button searchButton = (Button) findViewById(R.id.searchButton);
final EditText searchForm = (EditText) findViewById(R.id.searchForm);
searchButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
list = (ListView) findViewById(R.id.list);
adapter = new ListAdapter(MainActivity.this);
list.setAdapter(adapter);
search = searchForm.getText().toString();
Download_data download_data = new Download_data((download_complete) MainActivity.this);
download_data.download_data_from_link(search);
adapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(), search, Toast.LENGTH_LONG).show();
}
});
}
public void get_data(String data){
try {
JSONObject jsonObj = new JSONObject(data);
JSONArray data_array = jsonObj.getJSONArray("announcements");
for (int i = 0 ; i < data_array.length() ; i++)
{
JSONObject obj=new JSONObject(data_array.get(i).toString());
Countries add=new Countries();
add.name = obj.getString("message");
add.code = obj.getString("date");
countries.add(add);
}
adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
Download_data.java
public class Download_data implements Runnable {
public download_complete caller;
public interface download_complete{
public void get_data(String data);
}
Download_data(download_complete caller) {
this.caller = caller;
}
private String link;
public void download_data_from_link(String link){
this.link = link;
Thread t = new Thread(this);
t.start();
}
public void run() {
threadMsg(download(this.link));
}
private void threadMsg(String msg) {
if (!msg.equals(null) && !msg.equals("")) {
Message msgObj = handler.obtainMessage();
Bundle b = new Bundle();
b.putString("message", msg);
msgObj.setData(b);
handler.sendMessage(msgObj);
}
}
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
String Response = msg.getData().getString("message");
caller.get_data(Response);
}
};
public static String download(String url) {
URL website;
StringBuilder response = null;
try {
website = new URL(url);
HttpURLConnection connection = (HttpURLConnection) website.openConnection();
connection.setRequestProperty("charset", "utf-8");
BufferedReader in = new BufferedReader(
new InputStreamReader(
connection.getInputStream()));
response = new StringBuilder();
String inputLine;
while ((inputLine = in.readLine()) != null)
response.append(inputLine);
in.close();
} catch (Exception e) {
return "";
}
return response.toString();
}
ListAdapter.java
MainActivity main;
ListAdapter(MainActivity main)
{
this.main = main;
}
#Override
public int getCount() {
return main.countries.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
static class ViewHolderItem {
TextView name;
TextView code;
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
ViewHolderItem holder = new ViewHolderItem();
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) main.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.cell, null);
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.code = (TextView) convertView.findViewById(R.id.code);
convertView.setTag(holder);
}
else
{
holder = (ViewHolderItem) convertView.getTag();
}
holder.name.setText(this.main.countries.get(position).name);
holder.code.setText(this.main.countries.get(position).code);
return convertView;
}
It appears that the countries list is being added to each time in get_data(), but never cleared out. At the start of get_data, you most likely want to clear the countries list with the following call:
countries.clear();
Then the data in the countries list will be cleared out, the new downloaded data will be added to the countries list, and then updated in the view when the adapter is notified of the data change.

Using an interface from multiple async tasks

I have an interesting fragment with multiple spinners. THe first spinner, loads the data into the second spinner based on what was selected. It looks something like this:
When the fragment first loads the first spinner is "All" and it fills the listView with all the beers. Right now this is the only listView I can click on items without them force closing. The code for my portfolio is:
public class Portfolio extends Fragment implements PortfolioGetAllBeers.OnArticleSelectedListener {
String beerId = "";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//set layout here
final View theLayout = inflater.inflate(R.layout.activity_portfolio, container, false);
setHasOptionsMenu(true);
getActivity().setTitle("Portfolio");
//get user information
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
String userName = prefs.getString("userName", null);
String userID = prefs.getString("userID", null);
final Spinner portfolioType = (Spinner) theLayout.findViewById(R.id.portfolioSpinner);
portfolioType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
String portfolioChoice = portfolioType.getSelectedItem().toString();
Log.d("portfolio", portfolioChoice);
if( portfolioChoice.equals("All")){
//todo: clear second spinner
LinearLayout ll = (LinearLayout) theLayout.findViewById(R.id.addSpinnerLayout);
ll.removeAllViews();
//get userID
//get user data
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(selectedItemView.getContext());
String userID = prefs.getString("userID", null);
//construct url
String url = "myURL1";
//async task goes here
PortfolioGetAllBeers task = new PortfolioGetAllBeers(getActivity());
task.setOnArticleSelectedListener(Portfolio.this);
task.execute(url);
}
else if (portfolioChoice.equals("Brewery")){
LinearLayout ll = (LinearLayout) theLayout.findViewById(R.id.addSpinnerLayout);
ll.removeAllViews();
LayoutInflater inflater = (LayoutInflater)selectedItemView.getContext().getSystemService(selectedItemView.getContext().LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.addspinner_layout, null); // inflate addspinner
Spinner sp = (Spinner) v.findViewById(R.id.portfolioSpinner2); //portfolioSpinner2
ll.addView(v); // add the view to the linear layout
//todo: get breweries and fill spinner
//get userID
//get user data
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(selectedItemView.getContext());
String userID = prefs.getString("userID", null);
//construct url
String url = ""myurl2;
//async task goes here
PortfolioGetAllBeers task = new PortfolioGetAllBeers(getActivity());
task.setOnArticleSelectedListener(Portfolio.this);
task.execute(url);
}
else if (portfolioChoice.equals("Style")){
LinearLayout ll = (LinearLayout) theLayout.findViewById(R.id.addSpinnerLayout);
ll.removeAllViews();
LayoutInflater inflater = (LayoutInflater)selectedItemView.getContext().getSystemService(selectedItemView.getContext().LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.addspinner_layout, null); // inflate addspinner
Spinner sp = (Spinner) v.findViewById(R.id.portfolioSpinner2); //portfolioSpinner2
ll.addView(v); // add the view to the linear layout
//get userID
//get user data
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(selectedItemView.getContext());
String userID = prefs.getString("userID", null);
//construct url
String url = "myurl3";
//todo: async task goes here
new PortfolioGetAllStyles(selectedItemView.getContext()).execute(url);
}
else if (portfolioChoice.equals("Rating")){
LinearLayout ll = (LinearLayout) theLayout.findViewById(R.id.addSpinnerLayout);
ll.removeAllViews();
LayoutInflater inflater = (LayoutInflater)selectedItemView.getContext().getSystemService(selectedItemView.getContext().LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.addspinner_layout, null); // inflate addspinner
Spinner sp = (Spinner) v.findViewById(R.id.portfolioSpinner2); //portfolioSpinner2
ll.addView(v); // add the view to the linear layout
//get userID
//get user data
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(selectedItemView.getContext());
String userID = prefs.getString("userID", null);
//make array
//make array list for beer
final List<String> tasteList = new ArrayList<String>();
tasteList.add("1");
tasteList.add("2");
tasteList.add("3");
tasteList.add("4");
tasteList.add("5");
// Selection of the spinner
Spinner spinner = (Spinner) theLayout.findViewById(R.id.portfolioSpinner2);
// Application of the Array to the Spinner
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(selectedItemView.getContext(), android.R.layout.simple_spinner_item,tasteList );
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // The drop down view
spinner.setAdapter(spinnerArrayAdapter);
//todo: add on select for spinner 2
//add on item selected
final Spinner portfolioType = (Spinner) theLayout.findViewById(R.id.portfolioSpinner2);
portfolioType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
String portfolioChoice = portfolioType.getSelectedItem().toString();
//Toast.makeText(((Activity) c).getApplicationContext(), portfolioChoice, Toast.LENGTH_LONG).show();
final ListView lv = (ListView) theLayout.findViewById(R.id.allYourBeersList);
lv.setAdapter(null);
//get brewery beers
//get userID
//get user data
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(selectedItemView.getContext());
String userID = prefs.getString("userID", null);
try {
portfolioChoice = URLEncoder.encode(portfolioChoice, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//construct url
String url = "myurl4;
Log.d("portfolio" , url);
//async task goes here
new PortfolioGetAllBeers(selectedItemView.getContext()).execute(url);
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
// do nothing
}
});
}
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
// do nothing
}
});
// Inflate the layout for this fragment
return theLayout;
}
#Override
public void onArticleSelected(String bID, String brewery){
//code to execute on click
Fragment Fragment_one;
FragmentManager man= getFragmentManager();
FragmentTransaction tran = man.beginTransaction();
Fragment_one = new BeerPage();
final Bundle bundle = new Bundle();
bundle.putString("beerIDSent", bID);
bundle.putString("breweryIDSent", brewery);
Fragment_one.setArguments(bundle);
tran.replace(R.id.main, Fragment_one);//tran.
tran.addToBackStack(null);
tran.commit();
}
}
If the spinner is all on the first load it runs this portion of code from above:
if( portfolioChoice.equals("All")){
//todo: clear second spinner
LinearLayout ll = (LinearLayout) theLayout.findViewById(R.id.addSpinnerLayout);
ll.removeAllViews();
//get userID
//get user data
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(selectedItemView.getContext());
String userID = prefs.getString("userID", null);
//construct url
String url = "myURL1";
//async task goes here
PortfolioGetAllBeers task = new PortfolioGetAllBeers(getActivity());
task.setOnArticleSelectedListener(Portfolio.this);
task.execute(url);
}
Which calls this async task to load the listview:
public class PortfolioGetAllBeers extends AsyncTask<String, Void, String> {
Context c;
private ProgressDialog Dialog;
public PortfolioGetAllBeers (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();
}
//***************************code for on click
OnArticleSelectedListener listener;
public interface OnArticleSelectedListener{
public void onArticleSelected(String myString , String brewery);
}
public void setOnArticleSelectedListener(OnArticleSelectedListener listener){
this.listener = listener;
}
//*****************************end code for onClick
protected void onPostExecute(String result){
//decode json here
try{
JSONArray jsonArray = new JSONArray(result);
//acces listview
ListView lv = (ListView) ((Activity) c).findViewById(R.id.allYourBeersList);
//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 bID = jsonArray.getJSONObject(i).getString("breweryID");
//create object
ShortBeerInfo tempTaste = new ShortBeerInfo(beer, rate, beerID, bID);
//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;
//todo: go to beer page
listener.onArticleSelected(tempID, tempBrewID);
}
});
}
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 this loads the listview with items the onclicks work correctly through the interface. I am having trouble how to do the interface for the other options when the second spinner loads the data into the listview.
For example if you select style in the first spinner and an option in the second spinner as shown in the picture I posted above. It runs down this if statement in the code from Portfolio above:
else if (portfolioChoice.equals("Style")){
LinearLayout ll = (LinearLayout) theLayout.findViewById(R.id.addSpinnerLayout);
ll.removeAllViews();
LayoutInflater inflater = (LayoutInflater)selectedItemView.getContext().getSystemService(selectedItemView.getContext().LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.addspinner_layout, null); // inflate addspinner
Spinner sp = (Spinner) v.findViewById(R.id.portfolioSpinner2); //portfolioSpinner2
ll.addView(v); // add the view to the linear layout
//get userID
//get user data
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(selectedItemView.getContext());
String userID = prefs.getString("userID", null);
//construct url
String url = "myurl3";
//todo: async task goes here
new PortfolioGetAllStyles(selectedItemView.getContext()).execute(url);
}
When PortfolioGetAllStyles asyc task is execute I am not sure how to set the onclick to the interface. The code for PortfolioGetAllStyles is:
public class PortfolioGetAllStyles extends AsyncTask<String, Void, String> {
Context c;
private ProgressDialog Dialog;
public PortfolioGetAllStyles (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 Brewery List");
Dialog.setTitle("Loading");
Dialog.setCancelable(false);
Dialog.show();
}
protected void onPostExecute(String result){
//decode json here
try{
JSONArray jsonArray = new JSONArray(result);
//acces listview
final ListView lv = (ListView) ((Activity) c).findViewById(R.id.allYourBeersList);
//make array list for beer
final List<String> tasteList = new ArrayList<String>();
for(int i = 0; i < jsonArray.length(); i++) {
String beer = jsonArray.getJSONObject(i).getString("style");
String bID = jsonArray.getJSONObject(i).getString("breweryID");
String rate = "na";
String beerID = "na";
//create object
ShortBeerInfo tempTaste = new ShortBeerInfo(beer, rate, beerID, bID);
//add to arraylist
tasteList.add(beer);
}
// Selection of the spinner
Spinner spinner = (Spinner) ((Activity) c).findViewById(R.id.portfolioSpinner2);
// Application of the Array to the Spinner
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(c, android.R.layout.simple_spinner_item,tasteList );
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // The drop down view
spinner.setAdapter(spinnerArrayAdapter);
//add on item selected
final Spinner portfolioType = (Spinner) ((Activity) c).findViewById(R.id.portfolioSpinner2);
portfolioType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
String portfolioChoice = portfolioType.getSelectedItem().toString();
//Toast.makeText(((Activity) c).getApplicationContext(), portfolioChoice, Toast.LENGTH_LONG).show();
lv.setAdapter(null);
//get brewery beers
//get userID
//get user data
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(selectedItemView.getContext());
String userID = prefs.getString("userID", null);
try {
portfolioChoice = URLEncoder.encode(portfolioChoice, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//construct url
String url = "http://beerportfolio.com/app_getAllYourBeersStyle.php?u=" + userID + "&b=" + portfolioChoice;
Log.d("portfolio", url);
//async task goes here
new PortfolioGetAllBeers(selectedItemView.getContext()).execute(url);
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
// do nothing
}
});
}
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();
}
}
The error I am getting is:
03-03 14:30:00.495 20817-20817/com.beerportfolio.beerportfoliopro E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at com.beerportfolio.beerportfoliopro.PortfolioGetAllBeers$1.onItemClick(PortfolioGetAllBeers.java:114)
at android.widget.AdapterView.performItemClick(AdapterView.java:298)
at android.widget.AbsListView.performItemClick(AbsListView.java:1237)
at android.widget.ListView.performItemClick(ListView.java:4555)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3037)
at android.widget.AbsListView$1.run(AbsListView.java:3724)
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)
In short I think I need to get these lines working to tie the OnSelectedListener from the portfolio page to this async task:
PortfolioGetAllBeers task = new PortfolioGetAllBeers(c);
task.setOnArticleSelectedListener(Portfolio.this);
task.execute(url);
I just can not pass Portfolio.this into that line since we are not in Portfolio but another async task launched from it.
It seems that in this line:
new PortfolioGetAllBeers(selectedItemView.getContext()).execute(url);
You are creating and triggering async task witout setting listener. So you should do one of the following things:
set listener always before executing created async task
check if listener is not null before calling it:
if(listener != null){
listener.onArticleSelected(tempID, tempBrewID);
}

trying to launch a fragment from an async task

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();

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

Categories

Resources