我正在尝试将expandablelistview子数据保存到SharedPreferences
。保存工作正在进行,但是当我尝试加载它时,我会收到错误。
问题:
尝试加载设置并将其放入HashMap时,我会收到这些错误(缩写为3行):
08-24 12:40:05.138: E/AndroidRuntime(807): FATAL EXCEPTION: main
08-24 12:40:05.138: E/AndroidRuntime(807): java.lang.ClassCastException: java.lang.String cannot be cast to com.example.expandablelistview.NewsItem
08-24 12:40:05.138: E/AndroidRuntime(807): at com.example.expandablelistview.ExpandableListAdapter.getChildView(ExpandableListAdapter.java:62)
为了保存数据,我将使用以下代码:
SharedPreferences pref = context.getSharedPreferences("myPrefs", MODE_PRIVATE);
SharedPreferences.Editor editor= pref.edit();
for( Entry<String, List<NewsItem>> entry : listDataChild.entrySet() ) {
editor.putString( entry.getKey(), String.valueOf(entry.getValue())); // Save the values of listDataChild
}
editor.commit();
数据的输出是:
Yesterday: [[ headline=51.17346, 3.2252, Speed=2.10KM/H, Direction=158, date=18-8-2013 13:37:32]]
Older: [[ headline=51.74346, 3.23252, Speed=2.00KM/H, Direction=122, date=17-8-2013 11:40:30]]
Today: [[ headline=51.07346, 3.35252, Speed=0.00KM/H, Direction=122, date=19-8-2013 18:50:42]]
当尝试加载这些数据(这里发生的错误)并将其放入HashMap时,我会使用它(from here):
for( Entry<String, ?> entry : pref.getAll().entrySet() ) {
listDataChild.put( entry.getKey(), (List<NewsItem>) Arrays.asList(entry.getValue()) ); // Put it in listDataChild
}
数据的初始化发生在这里:
static void prepareListData(final Context context) {
listDataHeader = new ArrayList<String>();
listDataChild = new HashMap<String, List<NewsItem>>();
// Adding child data
listDataHeader.add("Today");
listDataHeader.add("Yesterday");
listDataHeader.add("Older");
List<NewsItem> today = new ArrayList<NewsItem>();
NewsItem newsData = new NewsItem();
newsData.setHeadline("51.07346, 3.35252");
newsData.setSpeed("0.00KM/H");
newsData.setDirection("122");
newsData.setDate("19-8-2013 18:50:42");
today.add(newsData);
List<NewsItem> yesterday = new ArrayList<NewsItem>();
newsData = new NewsItem();
newsData.setHeadline("51.17346, 3.2252");
newsData.setSpeed("2.10KM/H");
newsData.setDirection("158");
newsData.setDate("18-8-2013 13:37:32");
yesterday.add(newsData);
List<NewsItem> older = new ArrayList<NewsItem>();
newsData = new NewsItem();
newsData.setHeadline("51.74346, 3.23252");
newsData.setSpeed("2.00KM/H");
newsData.setDirection("122");
newsData.setDate("17-8-2013 11:40:30");
older.add(newsData);
listDataChild.put(listDataHeader.get(0), today);
listDataChild.put(listDataHeader.get(1), yesterday);
listDataChild.put(listDataHeader.get(2), older);
}
尝试过尝试:
我尝试更改listdataChild.put
以将数据加载到此:
listDataChild.put( entry.getKey(), new ArrayList<NewsItem>((Collection<? extends NewsItem>) Arrays.asList(entry.getValue())) );
对此:
listDataChild.put( entry.getKey(), (List<NewsItem>) new ArrayList(Arrays.asList(entry.getValue())) );
但没有任何结果。 (我有同样的错误)
问题:
是否可以将地图值转换为列表并将其放入HashMap listDataChild
?
或者我应该使用newsData.setHeadline("Value");
,newsData.setSpeed("Value");
等? (我不知道如何获取SharedPreferences
列表中的特定值)
(可以找到NewsItem.java
的来源here,可以找到ExpandableListAdapter.java
的来源here,MainActivity.java
的来源可以找到here)
答案 0 :(得分:2)
您需要将从String
以某种方式返回的SharedPreferences
转换为NewsItem
列表。单独演员不会那样做。
答案 1 :(得分:2)
正如其他人已经指出的那样,仅仅使用Arrays.asList()
并强制转换到数据列表的期望是不正确的,并且不起作用。在使用SharedPreferences.Editor.putString()
时,您将在首选项中插入String
,表示List.toString()
返回的字符串(将在方括号中打印其所有子项(使用toString()
) )。当您从首选项中获取此字符串时,需要将其构建为List
NewsItems
。如何做到这一点的一种方法如下:
for (Entry<String, ?> entry : pref.getAll().entrySet()) {
List<NewsItem> rowItems = new ArrayList<NewsItem>();
// the string from the preferences as it was saved
String prefContent = (String) entry.getValue();
// break against possible multiple NewsItems(I'm assuming that's
// why you use a List of NewsItems) for the same
// key (every NewsItem starts with * so we split after
// that(see the NewsItems.toString method))
String[] newsItems = prefContent.split("\\*");
for (String item : newsItems) {
// an item which doesn't have at least 50 characters
// isn't a valid NewsItem string representation(based on
// its toString() method)
if (item.length() > 50) {
// ; is the delimiter for the NewsItem's data
String[] components = item.split(";");
NewsItem ni = new NewsItem();
// for each of the four data components we split
// after = and then use the second value obtained as
// that will be the value for that component
ni.setHeadline((components[0].split("="))[1]);
ni.setSpeed((components[1].split("="))[1]);
ni.setDirection((components[2].split("="))[1]);
ni.setDate((components[3].split("="))[1]);
rowItems.add(ni);
}
}
listDataChild.put(entry.getKey(), rowItems);
}
上面的代码需要更改toString()
类的NewsItem
方法:
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("*headline=");
sb.append(headline);
sb.append(";");
sb.append("speed=");
sb.append(speed);
sb.append(";");
sb.append("direction=");
sb.append(direction);
sb.append(";");
sb.append("date=");
sb.append(date);
return sb.toString();
}
答案 2 :(得分:2)
此异常意味着您正在尝试将String对象分配给com.example.expandablelistview.NewsItem引用变量
我知道这无济于事,但无论如何
答案 3 :(得分:0)
我不确定 -
是否可以将地图值转换为列表并将其放入 HashMap listDataChild?
当您正在寻找将POJO数据保存在共享首选项中时。您可以使用 JSON 格式序列化NewsItemList及其包含的对象,然后将其作为String存储到SharedPreferences中。 Google-JSON是一个很好的api。
当您想要获取数据时,检索String并使用JSONArray检索每个对象并将其添加到新的NewsItemList。
否则,请尝试序列化您的对象为私人文件。这将帮助您超越SharedPreferences的putString(),putFloat(),putLong(),putInt()和putBoolean()。 谢谢。