Я пытаюсь заполнить счетчик от Mysql Databse через JSON. Дело в том, что данные экспортируются нормально. Но когда я нажимаю Spinner, чтобы открыть выпадающее меню, приложение вылетает.
Вывод JSON из базы данных: Выход
Ошибка:
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)
Мой адаптер:
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;
}
}
Мой 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());
}
Мой макет выглядит так:
Есть идеи, почему это происходит? Я раздуваю пользовательский макет, и все же он принимает его как ArrayAdapter<String>
,
Вы можете сделать то же самое, используя BaseAdapter:
public class SpiritsListAdapter extends BaseAdapter
Измените ваш конструктор так:
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;
}
и добавьте невыполненные методы, и вы сохраните свой метод getView таким, какой он есть.
Надеюсь, поможет!!!
Вы используете пятый список конструктора на эта страница, который требует, чтобы ваш второй параметр был
Идентификатор ресурса для файла макета, содержащего TextView, который используется при создании экземпляров представлений.
Вы не включили свой XML, есть ли у R.layout.spinner_item TextView
в этом?
Ваша стековая трасса имеет ArrayAdapter
в этом, потому что ваш SpiritsListAdapter
продолжается ArrayAdapter
так что каждый раз, когда вы звоните super()
или один из ArrayAdapter
методы, которые вы не переопределили, называется кодом из ArrayAdapter
класс используется.
Изменить: Вы пытались использовать этот конструктор: ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects)
(это шестой на странице, указанной выше), где вы даете ему идентификатор TextView
ты хочешь заселить? Там может быть проблема, вызванная двумя TextView
s в макете (как отмечено в комментариях).