Spinner选择后从MySQL数据库填充TextView的实现问题
Hey there! The issue here is that right now you're only storing the color string in your list, not the full Colors object that contains the density and strainer values you need. Let's fix this step by step:
Step 1: Update your Colors class to show the color name in Spinner
First, add a toString() method to your Colors class so the Spinner knows to display the color name when using the full object:
public class Colors { private int ui; private String color; private String density; private String strainer; // Your existing getters and setters here... @Override public String toString() { return color; // This tells the Spinner to show the color string } }
Step 2: Modify DataParser to store full Colors objects
Right now you're only adding the color string to a list. Let's change that to store complete Colors objects, and add a listener to pass the parsed list back to MainActivity:
public class DataParser extends AsyncTask<Void, Void, Integer> { // Interface to send parsed data back to MainActivity public interface OnDataParsedListener { void onDataParsed(ArrayList<Colors> colorList); } Context c; Spinner colorSpinner; String jsonData; ProgressDialog pd; ArrayList<Colors> colorList = new ArrayList<>(); // Store full Colors objects private OnDataParsedListener listener; // Updated constructor to include the listener public DataParser(Context c, Spinner colorSpinner, String jsonData, OnDataParsedListener listener) { this.c = c; this.colorSpinner = colorSpinner; this.jsonData = jsonData; this.listener = listener; } @Override protected void onPreExecute() { super.onPreExecute(); pd = new ProgressDialog(c); pd.setTitle("Parse"); pd.setMessage("Parsing"); pd.show(); } @Override protected Integer doInBackground(Void... params) { return this.parseData(); } @Override protected void onPostExecute(Integer result) { super.onPostExecute(result); pd.dismiss(); if (result == 0) { Toast.makeText(c, "Unable to Parse", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(c, "Parse Successful", Toast.LENGTH_SHORT).show(); // Use ArrayAdapter with Colors objects (toString() handles display) ArrayAdapter<Colors> adapter = new ArrayAdapter<>(c, android.R.layout.simple_list_item_1, colorList); colorSpinner.setAdapter(adapter); // Send the full list to MainActivity if (listener != null) { listener.onDataParsed(colorList); } } } private int parseData() { try { JSONArray ja = new JSONArray(jsonData); JSONObject jo = null; colorList.clear(); Colors s = null; for (int i = 0; i < ja.length(); i++) { jo = ja.getJSONObject(i); int ui = jo.getInt("ui"); String color = jo.getString("color"); String density = jo.getString("density"); String strainer = jo.getString("strainer"); s = new Colors(); s.setIu(ui); s.setColor(color); s.setDensity(density); s.setStrainer(strainer); colorList.add(s); // Add full object instead of just string } return 3; } catch (JSONException e) { e.printStackTrace(); } return 0; } }
Step 3: Update MainActivity to receive data and handle selection
Implement the listener interface, add a variable to hold the full color list, and initialize the second TextView for strainer:
public class MainActivity extends AppCompatActivity implements OnItemSelectedListener, DataParser.OnDataParsedListener { Context c; TextView colorDensity; TextView colorStrainer; // Add this for the second value Spinner colorSpinner; ArrayList<Colors> colorList; // Store full Colors objects here final static String urlAddress = "http://www.burtkuntzhandjobs.org/dbcolors.php"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); colorSpinner = findViewById(R.id.colorSpinner); colorDensity = findViewById(R.id.colorDensity); colorStrainer = findViewById(R.id.colorStrainer); // Initialize second TextView new Downloader(MainActivity.this, urlAddress, colorSpinner).execute(); colorSpinner.setOnItemSelectedListener(this); } // Receive the parsed full list from DataParser @Override public void onDataParsed(ArrayList<Colors> colorList) { this.colorList = colorList; } @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // Validate data and position before accessing if (colorList != null && position >= 0 && position < colorList.size()) { Colors selectedColor = colorList.get(position); // Populate TextViews with selected color's details colorDensity.setText("Density: " + selectedColor.getDensity()); colorStrainer.setText("Strainer: " + selectedColor.getStrainer()); } } @Override public void onNothingSelected(AdapterView<?> parent) { Toast.makeText(this, "Select Color", Toast.LENGTH_SHORT).show(); } }
Step 4: Update Downloader to pass the listener to DataParser
Modify the onPostExecute method in Downloader to include the listener when creating DataParser:
public class Downloader extends AsyncTask<Void, Void, String> { // ... existing code ... @Override protected void onPostExecute(String s) { super.onPostExecute(s); pd.dismiss(); if (s == null) { Toast.makeText(c, "Unable to Retrieve", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(c, "Success", Toast.LENGTH_SHORT).show(); // Pass MainActivity as the listener to DataParser DataParser parser = new DataParser(c, colorSpinner, s, (DataParser.OnDataParsedListener) c); parser.execute(); } } // ... existing downloadData method ... }
Why this works:
- We now store the full
Colorsobject for each database entry, so we have access to all fields when an item is selected. - The
toString()method inColorsensures the Spinner displays the color name correctly without extra adapter setup. - The listener pattern lets MainActivity receive the complete parsed list, so we can easily fetch the selected item's density and strainer values in
onItemSelected.
内容的提问来源于stack exchange,提问作者Aaron Steinberg

