[英]Strange Behavior when populating Spinner from Database
I am trying to populate a spinner from Mysql Databse through JSON. 我试图通过JSON从Mysql Databse填充一个微调器。 The thing is that the data are exported fine. 问题是数据导出正常。 But when I click the Spinner to show the dropdown menu the app crashes. 但是,当我单击Spinner显示下拉菜单时,应用程序崩溃了。
The JSON output from database: Output 数据库的JSON输出: 输出
The Error: 错误:
03-01 18:12:42.966 3214-3214/com.order.app.order E/ArrayAdapter﹕ You must supply a resource ID for a TextView
03-01 18:12:42.966 3214-3214/com.order.app.order D/AndroidRuntime﹕ Shutting down VM
03-01 18:12:42.967 3214-3214/com.order.app.order E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.order.app.order, PID: 3214
java.lang.IllegalStateException: ArrayAdapter requires the resource ID to be a TextView
at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:386)
at android.widget.ArrayAdapter.getDropDownView(ArrayAdapter.java:415)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to android.widget.TextView
at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:379)
at android.widget.ArrayAdapter.getDropDownView(ArrayAdapter.java:415)
My Adapter: 我的适配器:
public class SpiritsListAdapter extends ArrayAdapter<SpiritList> {
public SpiritsListAdapter(Context context, int layoutId, List<SpiritList> items) {
super(context, layoutId, items);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SpiritHolderItems holder;
if(convertView == null){
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
convertView = vi.inflate(R.layout.spinner_item, parent, false);
holder = new SpiritHolderItems();
holder.spiritName = (TextView)convertView.findViewById(R.id.spirit_name);
holder.spiritPrice = (TextView)convertView.findViewById(R.id.spirit_price);
convertView.setTag(holder);
}else{
holder = (SpiritHolderItems) convertView.getTag();
}
SpiritList current = getItem(position);
holder.spiritName.setText(current.getName());
holder.spiritPrice.setText(current.getPrice() + " €");
return convertView;
}
static class SpiritHolderItems {
TextView spiritName, spiritPrice;
}
}
My AsyncTask: 我的AsyncTask:
public class JsonReadTask extends AsyncTask<String , Void, List<SpiritList>> {
public JsonReadTask() {
super();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(Gins.this, ProgressDialog.THEME_DEVICE_DEFAULT_DARK);
pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pDialog.setIndeterminate(true);
pDialog.setMessage(getString(R.string.get_stocks));
pDialog.setCancelable(false);
pDialog.setInverseBackgroundForced(true);
pDialog.show();
}
@Override
protected List<SpiritList> doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
try {
HttpResponse response = httpclient.execute(httppost);
jsonResult = inputStreamToString(
response.getEntity().getContent()).toString();
customList = new ArrayList<>();
JSONObject jsonResponse = new JSONObject(jsonResult);
JSONArray jsonMainNode = jsonResponse.optJSONArray("gins");
for (int i = 0; i < jsonMainNode.length(); i++) {
JSONObject jsonChildNode = jsonMainNode.getJSONObject(i);
String name = jsonChildNode.optString("name");
String price = jsonChildNode.optString("price");
customList.add(new SpiritList(name, price));
}
return customList;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private StringBuilder inputStreamToString(InputStream is) {
String rLine = "";
StringBuilder answer = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((rLine = rd.readLine()) != null) {
answer.append(rLine);
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return answer;
}
@Override
protected void onPostExecute(List<SpiritList> customList) {
if(customList == null){
Log.d("ERORR", "No result to show.");
return;
}
ListDrawer(customList);
pDialog.dismiss();
}
}// end async task
public void accessWebService() {
JsonReadTask task = new JsonReadTask();
task.execute(new String[]{url});
}
public void ListDrawer(List<SpiritList> customList) {
adapterGins = new SpiritsListAdapter(getApplicationContext(), R.layout.spinner_item, customList);
adapterGins.notifyDataSetChanged();
spDrinks.setAdapter(adapterGins);
Log.d("Spinner Count", "The Spinner count is " + spDrinks.getCount());
}
My Layout looks like: 我的布局看起来像:
Any ideas why is this happening? 任何想法为什么会发生这种情况? I am inflating the custom layout and yet it takes it as an ArrayAdapter<String>
. 我正在膨胀自定义布局,但它将它作为ArrayAdapter<String>
。
You're using the fifth constructor list on this page , which requires that your second parameter be 您正在使用此页面上的第五个构造函数列表,这需要您的第二个参数
The resource ID for a layout file containing a TextView to use when instantiating views. 包含要在实例化视图时使用的TextView的布局文件的资源ID。
You haven't included your xml, does R.layout.spinner_item have a TextView
in it? 你没有包含你的xml,R.layout.spinner_item中有一个TextView
吗?
Your stacktrace has ArrayAdapter
in it because your SpiritsListAdapter
extends ArrayAdapter
, so every time you call super()
or one of the ArrayAdapter
's methods that you haven't overriden is called, code from the ArrayAdapter
class is used. 您的stacktrace中包含ArrayAdapter
,因为您的SpiritsListAdapter
扩展了ArrayAdapter
,因此每次调用super()
或调用您未覆盖的ArrayAdapter
方法之一时,都会使用ArrayAdapter
类中的代码。
Edit: Have you tried using this constuctor: ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects)
(it's the sixth one on the page linked to above) where you give it the id of the TextView
you want to populate? 编辑:您是否尝试过使用此构造函数: ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects)
(它是链接到上面的页面上的第六个),您可以在其中为其提供所需TextView
的ID填充? There could be a problem caused by having two TextView
s in the layout (as noted in the comments). 在布局中使用两个TextView
可能会导致问题(如注释中所述)。
You can do the same thing using BaseAdapter as such: 您可以使用BaseAdapter执行相同的操作:
public class SpiritsListAdapter extends BaseAdapter
Modify your constructor like this: 像这样修改你的构造函数:
private List<SpiritList> objects;
private Context context;
public SpiritsListAdapter(Context context ,List<SpiritList> objects) {
this.context = context;
this.objects = objects;
}
@Override
public int getCount() {
return objects.size();
}
@Override
public Object getItem(int position) {
return objects.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
and add the unimplemented methods and you keep your getView method as it is. 并添加未实现的方法,并保持您的getView方法不变。
Hope it helps!!! 希望能帮助到你!!!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.