问题
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.
回答1:
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);
}
来源:https://stackoverflow.com/questions/22155201/using-an-interface-from-multiple-async-tasks