从 ListView 抛出 NoSuchElementException
NoSuchElementException thrown from ListView
我有一个 ListView,我将空适配器传递给它,然后在从服务器拉取数据后填充它:
Context mContext;
List<Recipe> menuList = new ArrayList<>();
private Party party;
public MenuAdapter(Context context) {
mContext = context;
party = PartyPlannerConfig.getCurrentParty();
}
public void replaceList(final @NonNull List<Recipe> menuList) {
this.menuList = menuList;
notifyDataSetChanged();
}
在我的 getView 方法中,我填充了视图,我还在其中一个视图上设置了点击侦听器,其中 adds/removes 项来自与填充适配器的列表不同的列表:
@Override
public View getView(int position, View convertView, final ViewGroup parent) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.content_recipe_element, parent, false);
final TextView mButton = (TextView) view.findViewById(R.id.name);
final ImageView mImage = (ImageView) view.findViewById(R.id.image);
final ImageView mBtnFavourite = (ImageView) view.findViewById(R.id.btn_favourite);
final Recipe recipe = getItem(position);
Picasso.with(mContext).load(recipe.getTableImageURL()).into(mImage);
mButton.setText(recipe.getRecipeName());
final List<Recipe> currentRecipes = new ArrayList<>(party.getMenuItems());
final List<Recipe> modifiedRecipes = new ArrayList<>(party.getMenuItems());
mBtnFavourite.setSelected(currentRecipes.contains(recipe));
mBtnFavourite.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
if (!mBtnFavourite.isSelected()) {
modifiedRecipes.add(recipe);
} else {
if (modifiedRecipes.contains(recipe)) {
modifiedRecipes.remove(recipe);
}
}
party.setMenuItems(modifiedRecipes);
notifyDataSetChanged();
new SavePartyTask().execute(party);
} catch (Exception ignore) { }
}
});
mImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mContext.startActivity(RecipeDetailActivity.makeIntent(mContext, recipe));
}
});
return view;
}
出于某种原因,当我一遍又一遍地单击 mBtnFavourite 时,我得到了一个 NoSuchElementException:
AndroidRuntime:...
java.util.NoSuchElementException
at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:576)
at com.backendless.FootprintsManager$Inner.updateFootprintForObject(FootprintsManager.java:257)
at com.backendless.Persistence.handleResponse(Persistence.java:196)
at com.backendless.async.message.AsyncMessage$ResponseHandler.handle(AsyncMessage.java:64)
at com.backendless.async.message.AsyncMessage.handleCallback(AsyncMessage.java:41)
at com.backendless.core.AndroidCarrier.handleMessage(AndroidCarrier.java:37)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
下面是我的 AsyncTask 代码:
private class SavePartyTask extends AsyncTask<Party, Void, Void> {
@Override
protected Void doInBackground(Party... params) {
new PartyController(mContext).saveParty(params[0]);
return null;
}
}
这是 PartyController 的代码:
public class PartyController 扩展控制器 {
private static PartyController instance;
public PartyController(Context context) {
super(context);
}
public synchronized static PartyController getInstance(Context context) {
if(instance == null) {
instance = new PartyController(context);
}
return instance;
}
public void getPartyList() throws UserException {
mJobManager.addJobInBackground(new GetPartyListJob());
}
public void addParty(String partyName, Occasion occasion, Moodboard inspiration) throws UserException {
final Party party = new Party();
final Long currentTime = (System.currentTimeMillis() / 1000L);
party.setName(partyName);
party.setCreated(currentTime);
party.setOccasion(occasion);
party.setMoodboard(inspiration);
final Calendar c = Calendar.getInstance();
party.setUpdated(c.getTimeInMillis());
PartyPlannerLog.v(WHOAMI, "Logged in user: " + Backendless.UserService.loggedInUser());
mJobManager.addJobInBackground(new SavePartyJob(party));
}
public void deleteParty(Party party) throws UserException {
mJobManager.addJobInBackground(new DeletePartyJob(party));
}
public void saveParty(Party party) {
final Calendar c = Calendar.getInstance();
party.setUpdated(c.getTimeInMillis());
PartyPlannerConfig.setCurrentParty(party);
mJobManager.addJobInBackground(new SavePartyJob(party));
}
}
我此时感到非常困惑,并且一整天都在努力解决这个问题。请帮忙!!!
我认为您遇到了并发问题:
party.setMenuItems(modifiedRecipes);
new SavePartyTask().execute(party);
这里是:
PartyPlannerConfig.setCurrentParty(party);
mJobManager.addJobInBackground(new SavePartyJob(party));
我不确定这 2 个函数的作用,但如果它们保留对列表的引用而不是制作副本,那么您可以在后台线程中访问列表,而 UI 线程单击按钮修改列表。
一个简单的解决方案是在派对对象中复制一份列表,而不是保留对原始列表的引用:
party.setMenuItems(modifiedRecipes);
确保此 setMenuItems 复制修改后的食谱,而不是保留对原始食谱的引用。
是的,这看起来像是并发问题。仔细调试您的代码,您在其中根据标志向列表中添加和删除项目。我想,此刻您的代码试图删除存在 none 的 element 。使用 logger 跟踪列表中的项目,并检查您是否正在调用空 List 。
我有一个 ListView,我将空适配器传递给它,然后在从服务器拉取数据后填充它:
Context mContext;
List<Recipe> menuList = new ArrayList<>();
private Party party;
public MenuAdapter(Context context) {
mContext = context;
party = PartyPlannerConfig.getCurrentParty();
}
public void replaceList(final @NonNull List<Recipe> menuList) {
this.menuList = menuList;
notifyDataSetChanged();
}
在我的 getView 方法中,我填充了视图,我还在其中一个视图上设置了点击侦听器,其中 adds/removes 项来自与填充适配器的列表不同的列表:
@Override
public View getView(int position, View convertView, final ViewGroup parent) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.content_recipe_element, parent, false);
final TextView mButton = (TextView) view.findViewById(R.id.name);
final ImageView mImage = (ImageView) view.findViewById(R.id.image);
final ImageView mBtnFavourite = (ImageView) view.findViewById(R.id.btn_favourite);
final Recipe recipe = getItem(position);
Picasso.with(mContext).load(recipe.getTableImageURL()).into(mImage);
mButton.setText(recipe.getRecipeName());
final List<Recipe> currentRecipes = new ArrayList<>(party.getMenuItems());
final List<Recipe> modifiedRecipes = new ArrayList<>(party.getMenuItems());
mBtnFavourite.setSelected(currentRecipes.contains(recipe));
mBtnFavourite.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
if (!mBtnFavourite.isSelected()) {
modifiedRecipes.add(recipe);
} else {
if (modifiedRecipes.contains(recipe)) {
modifiedRecipes.remove(recipe);
}
}
party.setMenuItems(modifiedRecipes);
notifyDataSetChanged();
new SavePartyTask().execute(party);
} catch (Exception ignore) { }
}
});
mImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mContext.startActivity(RecipeDetailActivity.makeIntent(mContext, recipe));
}
});
return view;
}
出于某种原因,当我一遍又一遍地单击 mBtnFavourite 时,我得到了一个 NoSuchElementException:
AndroidRuntime:...
java.util.NoSuchElementException
at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:576)
at com.backendless.FootprintsManager$Inner.updateFootprintForObject(FootprintsManager.java:257)
at com.backendless.Persistence.handleResponse(Persistence.java:196)
at com.backendless.async.message.AsyncMessage$ResponseHandler.handle(AsyncMessage.java:64)
at com.backendless.async.message.AsyncMessage.handleCallback(AsyncMessage.java:41)
at com.backendless.core.AndroidCarrier.handleMessage(AndroidCarrier.java:37)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
下面是我的 AsyncTask 代码:
private class SavePartyTask extends AsyncTask<Party, Void, Void> {
@Override
protected Void doInBackground(Party... params) {
new PartyController(mContext).saveParty(params[0]);
return null;
}
}
这是 PartyController 的代码:
public class PartyController 扩展控制器 {
private static PartyController instance;
public PartyController(Context context) {
super(context);
}
public synchronized static PartyController getInstance(Context context) {
if(instance == null) {
instance = new PartyController(context);
}
return instance;
}
public void getPartyList() throws UserException {
mJobManager.addJobInBackground(new GetPartyListJob());
}
public void addParty(String partyName, Occasion occasion, Moodboard inspiration) throws UserException {
final Party party = new Party();
final Long currentTime = (System.currentTimeMillis() / 1000L);
party.setName(partyName);
party.setCreated(currentTime);
party.setOccasion(occasion);
party.setMoodboard(inspiration);
final Calendar c = Calendar.getInstance();
party.setUpdated(c.getTimeInMillis());
PartyPlannerLog.v(WHOAMI, "Logged in user: " + Backendless.UserService.loggedInUser());
mJobManager.addJobInBackground(new SavePartyJob(party));
}
public void deleteParty(Party party) throws UserException {
mJobManager.addJobInBackground(new DeletePartyJob(party));
}
public void saveParty(Party party) {
final Calendar c = Calendar.getInstance();
party.setUpdated(c.getTimeInMillis());
PartyPlannerConfig.setCurrentParty(party);
mJobManager.addJobInBackground(new SavePartyJob(party));
}
} 我此时感到非常困惑,并且一整天都在努力解决这个问题。请帮忙!!!
我认为您遇到了并发问题:
party.setMenuItems(modifiedRecipes);
new SavePartyTask().execute(party);
这里是:
PartyPlannerConfig.setCurrentParty(party);
mJobManager.addJobInBackground(new SavePartyJob(party));
我不确定这 2 个函数的作用,但如果它们保留对列表的引用而不是制作副本,那么您可以在后台线程中访问列表,而 UI 线程单击按钮修改列表。
一个简单的解决方案是在派对对象中复制一份列表,而不是保留对原始列表的引用:
party.setMenuItems(modifiedRecipes);
确保此 setMenuItems 复制修改后的食谱,而不是保留对原始食谱的引用。
是的,这看起来像是并发问题。仔细调试您的代码,您在其中根据标志向列表中添加和删除项目。我想,此刻您的代码试图删除存在 none 的 element 。使用 logger 跟踪列表中的项目,并检查您是否正在调用空 List 。