#android #arrays #arraylist #expandablelistview
#Android #массивы #arraylist #расширяемый список просмотра
Вопрос:
Я пытаюсь создать расширяемый список внутри моей активности, который показывает типы вин на верхнем уровне и отдельные бутылки вина на втором уровне. Я считываю все свои данные из файла CSV, который я создал и заполнил 8 конкретными бутылками вина, которые на данный момент относятся к одной категории. Однако у меня возникла проблема: я считываю свои данные из csv-файла в массив и могу сообщить об этом в журнал по мере чтения, и он отображается правильно. Но как только я пытаюсь поместить его в свой адаптер, а затем в listview, массив заполняется 8 идентичными объектами Wine, которые являются тем, что является последним в моем файле.
Вот код, который я использую для чтения файла и создания массива объектов Wine.
Редактировать: я изменил свой код, чтобы проверить запись в массив после завершения цикла while, и я получаю тот же результат. Это более новая версия кода.
handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
Log.i(myTag, "Notify Change");
//By the time I get to here every object in the array is identical
for(int i = 0; i < chrd.length; i ){
Log.i(myTag,i " " chrd[i].toString());
}
super.handleMessage(msg);
}
};
Runnable r = new Runnable(){
public void run()
{
current = new Chardonnay();
//final int ITEMS = 15;
int count = 0;
try {
File myFile = new File ("/sdcard/chardonnay.txt");
fis = new FileInputStream(myFile);
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
String line;
while ((line = reader.readLine()) != null) {
String[] RowData = line.split(",");
current.setName(RowData[0]);
current.setPlace(RowData[1]);
current.setDescription(RowData[2]);
current.setYear(Integer.valueOf(RowData[3]));
current.setPriceBottle(Integer.valueOf(RowData[4]));
current.setPriceGlass(Integer.valueOf(RowData[5]));
chrd[count] = current;
Log.i(myTag, count " " chrd[count]);
count ;
}
for(int i = 0; i < chrd.length; i ){
Log.i(myTag,i " " chrd[i]);
}
}
catch (IOException ex) {
// handle exception
ex.printStackTrace();
}
handler.sendEmptyMessage(1);
try {
fis.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(r);
thread.start();
}
И вот вывод журнала, который создается при выполнении этого:
04-13 15:45:09.390: INFO/One2OneWineMenu(6472): 0 Wine [name=Acre, place=Central Coast, description=Seductive apple pie crust and lemon blossom aromas introduce crisp juicy flavors enriched by a creaminess resulting from surlie barrel aging, year=2008, priceBottle=25, priceGlass=7]
04-13 15:45:09.390: INFO/One2OneWineMenu(6472): 1 Wine [name=Silver Palm, place=North Coast, description=Fermented in stainless steel* this wine's delicate fruit characteristics were preserved without any overbearing flavors that an oak barrel might impart, year=2009, priceBottle=30, priceGlass=10]
04-13 15:45:09.390: INFO/One2OneWineMenu(6472): 2 Wine [name=Franciscan, place=Napa Valley, description=Ripe* generous aromas of apple* pear* and honey with toasty oak. Lively* rich creamy and supple with notes of vanilla on the finish, year=2009, priceBottle=30, priceGlass=-1]
04-13 15:45:09.390: INFO/One2OneWineMenu(6472): 3 Wine [name=Sonoma Cutrer, place=Russian River, description=The 2nd most popular chardonnay in Wamp;S Restaurant Poll* this wine is beautifully balanced with well integrated oak, year=2008, priceBottle=35, priceGlass=11]
04-13 15:45:09.390: INFO/One2OneWineMenu(6472): 4 Wine [name=Matanzas Creek, place=Sonoma, description=92 pts WE* this wine has a silky texture with flavors of lemon cream* peach and pear which feels elegant and creamy on the palate, year=2007, priceBottle=40, priceGlass=-1]
04-13 15:45:09.390: INFO/One2OneWineMenu(6472): 5 Wine [name=Silver by Mer Soleil, place=Santa Lucia Highlands, description=Combines ripe* intense peach* nectarine and tangerine fruit with touches of floral and spice, year=2007, priceBottle=40, priceGlass=-1]
04-13 15:45:09.390: INFO/One2OneWineMenu(6472): 6 Wine [name=Jordan, place=Russian River, description=Voted Best Chardonnay by respected wine journalists who attended 2010 Critics Challenge, year=2008, priceBottle=50, priceGlass=-1]
04-13 15:45:09.390: INFO/One2OneWineMenu(6472): 7 Wine [name=Ramey, place=Santa Lucia Highlands, description=94 pts RP* intense and vibrant* shows full-bodied citrus* melon* and hazelnut flavors that turn subtle and offer hints of fig/tangerine, year=2007, priceBottle=90, priceGlass=-1]
04-13 15:45:09.405: INFO/One2OneWineMenu(6472): Notify Change
04-13 15:45:09.405: INFO/One2OneWineMenu(6472): 0 Wine [name=Ramey, place=Santa Lucia Highlands, description=94 pts RP* intense and vibrant* shows full-bodied citrus* melon* and hazelnut flavors that turn subtle and offer hints of fig/tangerine, year=2007, priceBottle=90, priceGlass=-1]
04-13 15:45:09.405: INFO/One2OneWineMenu(6472): 1 Wine [name=Ramey, place=Santa Lucia Highlands, description=94 pts RP* intense and vibrant* shows full-bodied citrus* melon* and hazelnut flavors that turn subtle and offer hints of fig/tangerine, year=2007, priceBottle=90, priceGlass=-1]
04-13 15:45:09.405: INFO/One2OneWineMenu(6472): 2 Wine [name=Ramey, place=Santa Lucia Highlands, description=94 pts RP* intense and vibrant* shows full-bodied citrus* melon* and hazelnut flavors that turn subtle and offer hints of fig/tangerine, year=2007, priceBottle=90, priceGlass=-1]
04-13 15:45:09.405: INFO/One2OneWineMenu(6472): 3 Wine [name=Ramey, place=Santa Lucia Highlands, description=94 pts RP* intense and vibrant* shows full-bodied citrus* melon* and hazelnut flavors that turn subtle and offer hints of fig/tangerine, year=2007, priceBottle=90, priceGlass=-1]
04-13 15:45:09.405: INFO/One2OneWineMenu(6472): 4 Wine [name=Ramey, place=Santa Lucia Highlands, description=94 pts RP* intense and vibrant* shows full-bodied citrus* melon* and hazelnut flavors that turn subtle and offer hints of fig/tangerine, year=2007, priceBottle=90, priceGlass=-1]
04-13 15:45:09.405: INFO/One2OneWineMenu(6472): 5 Wine [name=Ramey, place=Santa Lucia Highlands, description=94 pts RP* intense and vibrant* shows full-bodied citrus* melon* and hazelnut flavors that turn subtle and offer hints of fig/tangerine, year=2007, priceBottle=90, priceGlass=-1]
04-13 15:45:09.405: INFO/One2OneWineMenu(6472): 6 Wine [name=Ramey, place=Santa Lucia Highlands, description=94 pts RP* intense and vibrant* shows full-bodied citrus* melon* and hazelnut flavors that turn subtle and offer hints of fig/tangerine, year=2007, priceBottle=90, priceGlass=-1]
04-13 15:45:09.405: INFO/One2OneWineMenu(6472): 7 Wine [name=Ramey, place=Santa Lucia Highlands, description=94 pts RP* intense and vibrant* shows full-bodied citrus* melon* and hazelnut flavors that turn subtle and offer hints of fig/tangerine, year=2007, priceBottle=90, priceGlass=-1]
Я попробовал ту же логическую концепцию, но с ArrayList вместо Wine [] и у него та же проблема. Я в тупике, я никогда не видел, чтобы содержимое массива просто менялось без видимой причины, подобной этой. Возможно, я упускаю из виду что-то относительно простое, у кого-нибудь есть идеи, что здесь может происходить?
Комментарии:
1. требуется определение chrd… полный финалов, статики и прочего
2. Как вы форматируете данные для расширяемого ListAdapter. По моему опыту, группы должны быть отформатированы как List<HashMap<Строка, объект>>, а дочерние элементы — как List<Список<HashMap<строка, объект>>>. Я предоставил некоторый пример кода в ответе для иллюстрации.
3. chrd определяется следующим образом: Wine[] chrd; и chrd = new Wine[8];
Ответ №1:
Вы присваиваете один и тот же объект ( current
) всем ячейкам chrd
, вот почему в итоге вы получаете последнее значение. Вы должны инициализировать current
внутри цикла, чтобы исправить это.
while ((line = reader.readLine()) != null) {
current = new Chardonnay();
String[] RowData = line.split(",");
current.setName(RowData[0]);
current.setPlace(RowData[1]);
current.setDescription(RowData[2]);
current.setYear(Integer.valueOf(RowData[3]));
current.setPriceBottle(Integer.valueOf(RowData[4]));
current.setPriceGlass(Integer.valueOf(RowData[5]));
chrd[count] = current;
Log.i(myTag, count " " chrd[count]);
count ;
}
Комментарии:
1. Спасибо! Вы правы. Это работает, если я делаю это таким образом. Теперь я пытаюсь разобраться, почему он будет правильно сообщать в первый раз (из журнала, который внутри цикла), но затем переключается, как только я вышел из цикла. Это потому, что я просто присваиваю ссылку на current в массиве? Если бы я использовал что-то вроде chrd[count].setName(rowData[0]); и т.д. … Вместо того, чтобы делать все это с текущим объектом, я думаю, что это также позволило бы избежать этой проблемы.
2. Первый раз происходит внутри вашего цикла, поэтому он выводит текущее значение объекта, в следующем цикле значение уже изменилось во всех ячейках, поскольку это один и тот же объект.
Ответ №2:
Проблема в этой строке:
current = new Chardonnay();
Вы создаете только один объект, каждый цикл while заменяет свойства в этом объекте, и, таким образом, вы заканчиваете с последним.
Переместите создание объекта внутри цикла while.
Ответ №3:
переместите «current = new Chardonnay();» в цикл while
в вашем коде каждый элемент массива указывает на один и тот же экземпляр Chardonnay
Ответ №4:
По моему опыту, именно так мне приходилось форматировать данные для групп расширяемого списка адаптеров:
ArrayList<HashMap<String, String>> alist = new ArrayList<HashMap<String, String>>();
...
//provided there are entries in the database, iterate through them all. create a hashmap using "company" as the key and
//the company as the item and add this hashmap to the array of maps.
if (cursor.moveToFirst()) {
do {
HashMap<String, String> m = new HashMap<String, String>();
m.put("company", cursor.getString(cursor.getColumnIndex(CompanyAndProductDatabaseAdapter.company_column)));
alist.add(m);
} while (cursor.moveToNext());
}
Комментарии:
1. Хм, похоже, что другие ответы более уместны. Не обращайте внимания на это, как только это сработает для вас.