2016-06-21 14 views
2

Ich habe eine Listview, die ich einen leeren Adapter übergeben, die mich dann einmal Daten füllen vom Server ziehen:NoSuchElementException geworfen von 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(); 
} 

In meiner getView Methode, besiedeln ich Ansichten und ich habe auch ein Klick Zuhörer der Ansichten auf eine, die Elemente aus einer separaten Liste von dem/entfernt hinzufügt, die den Adapter ist bevölkern:

@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; 
} 

aus irgendeinem Grund, wenn ich mBtnFavourite immer und immer wieder klicken, erhalte ich eine 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$4.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$1.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) 

Unten ist mein AsyncTask Code:

private class SavePartyTask extends AsyncTask<Party, Void, Void> { 
    @Override 
    protected Void doInBackground(Party... params) { 
     new PartyController(mContext).saveParty(params[0]); 
     return null; 
    } 
} 

und dies ist der Code für PartyController:

public class PartyController erweitert Regler {

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)); 
} 

} ich über bin verwirrt zu dieser Zeit und habe versucht, dies für einen ganzen Tag herauszufinden. Plz helfen !!!

+0

Bitte senden Sie Ihren asynchronen Aufgabencode und die Party-Klasse. – Francesc

+0

@Francesc, fertig –

Antwort

1

Ich glaube, dass Sie eine Gleichzeitigkeit Problem haben:

party.setMenuItems(modifiedRecipes); 
new SavePartyTask().execute(party); 

, die hier geht:

PartyPlannerConfig.setCurrentParty(party); 
mJobManager.addJobInBackground(new SavePartyJob(party)); 

Ich bin nicht sicher, was diese zwei Funktionen zu tun, aber wenn sie halten einen Verweis auf die Wenn Sie eine Liste erstellen, statt eine Kopie zu erstellen, können Sie auf eine Liste in Ihrem Hintergrund-Thread zugreifen, während der UI-Thread die Liste beim Klicken auf die Schaltfläche ändert.

Eine einfache Lösung wäre hier eine Kopie der Liste in Ihrer Partei Objekt zu machen, anstatt einen Verweis auf das Original zu halten:

party.setMenuItems(modifiedRecipes); 

dieses setMenuItems stellen Sie sicher, eine Kopie von modifiedRecipes macht statt einen Verweis auf das Original behalten.

+0

Danke. Ich denke, Nebenläufigkeit ist in der Tat das Problem hier. –

1

Ja, es sieht aus wie ein Nebenläufigkeitsproblem. Debuggen Sie Ihren Code sorgfältig, indem Sie Elemente basierend auf Flags zur Liste hinzufügen und daraus entfernen. Ich schätze, in einem Moment versucht Ihr Code, ein Element zu entfernen, wo es keines gibt. Verfolgen Sie die Einträge in Ihrer Liste mithilfe der Protokollfunktion und überprüfen Sie, ob Sie eine leere Liste aufrufen.

Verwandte Themen