2011-11-24 23 views
17

Otrzymuję zduplikowane elementy w widoku listy. Przewijanie w tył iw dół czasami zmienia kolejność elementów. Przeszukałem i znalazłem wiele wątków zgłaszających ten błąd, ale żaden z nich nie pomógł mi w rozwiązaniu problemu.Zduplikowane wpisy w ListView

Oto mój kod:

Aktywność:

package com.github.progval.SeenDroid; 

import java.util.ArrayList; 
import java.util.List; 

import com.github.progval.SeenDroid.lib.Connection; 
import com.github.progval.SeenDroid.lib.Message; 
import com.github.progval.SeenDroid.lib.MessageFetcher; 
import com.github.progval.SeenDroid.lib.Query.ParserException; 

import android.app.Activity; 
import android.app.ListActivity; 
import android.content.SharedPreferences; 
import android.os.Bundle; 

public class ShowUserActivity extends ListActivity { 
    private Connection connection; 

    public ArrayList<Message> listMessages = new ArrayList<Message>(); 
    public MessageAdapter adapter; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.profile); 
     this.connection = new Connection(); 
     this.setTitle(R.string.homefeed_title); 


     this.listMessages = new MessageFetcher(this.connection).fetchUser(); 
     this.bindUi(); 
    } 

    private void bindUi() { 
     this.adapter = new MessageAdapter(this, this.listMessages); 
     this.setListAdapter(adapter); 

     // TODO Bind buttons 
    } 
} 

MessageAdapter:

package com.github.progval.SeenDroid; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.zip.Inflater; 

import com.github.progval.SeenDroid.lib.Message; 

import android.content.Context; 
import android.text.Layout; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.webkit.WebView; 
import android.widget.ArrayAdapter; 
import android.widget.BaseAdapter; 
import android.widget.LinearLayout; 
import android.widget.TextView; 

public class MessageAdapter extends BaseAdapter { 
    private Context context; 
    private List<Message> items = new ArrayList<Message>(); 
    private int lastPosition = 0; 

    public MessageAdapter(Context context, List<Message> items) { 
     super(); 
     this.context = context; 
     this.items = items; 
    } 

    public View getView(int position, View convertView, ViewGroup parent) { 

     if (null == convertView) { 
      LinearLayout view; 
      view = (LinearLayout) LinearLayout.inflate(this.context, R.layout.message, null); 
      Log.d("SeenDroid", String.format("Get view %d", position)); 
      TextView title = new TextView(view.getContext()); 
      title.setText(this.items.get(position).getTitle()); 
      view.addView(title); 
      return view; 
     } else { 
      return convertView; 
     } 
    } 


    @Override 
    public int getCount() { 
     return this.items.size(); 
    } 


    @Override 
    public Object getItem(int location) { 
     return this.items.get(location); 
    } 


    @Override 
    public long getItemId(int arg0) { 
     return arg0; 
    } 


} 

Nawiasem mówiąc, wyjście jest:

D/SeenDroid(30939): Get view 0 
D/SeenDroid(30939): Get view 1 
D/SeenDroid(30939): Get view 2 
D/SeenDroid(30939): Get view 3 
D/SeenDroid(30939): Get view 4 
D/SeenDroid(30939): Get view 5 
D/SeenDroid(30939): Get view 6 
D/SeenDroid(30939): Get view 7 
D/SeenDroid(30939): Get view 8 
D/SeenDroid(30939): Get view 0 
D/SeenDroid(30939): Get view 16 

Pozdrowienia, ProgVal

Odpowiedz

32

Spróbuj tego:

public View getView(int position, View convertView, ViewGroup parent) { 

    if (null == convertView) { 
     LinearLayout view = (LinearLayout) LinearLayout.inflate(this.context, 
      R.layout.message, null); 
     Log.d("SeenDroid", String.format("Get view %d", position)); 
     TextView title = new TextView(view.getContext()); 
     title.setText(this.items.get(position).getTitle()); 
     view.addView(title); 
     return view; 
    } else { 
     LinearLayout view = (LinearLayout) convertView; 
     TextView title = (TextView) view.getChildAt(0); 
     title.setText(this.items.get(position).getTitle()); 
     return convertView; 
    } 
} 

Objaśnienie: masz duplikaty ponieważ wykazy obiektów na Androidzie ponowne UI. Oczekuje się ponownego użycia convertView zamiast tworzenia nowego, jeśli nie jest zerowy. Oczywiście, jesteś odpowiedzialny za ustawienie odpowiedniej wartości dla ponownie wykorzystywanej instancji. W przeciwnym razie wartość pozostaje z ostatniego "użycia".

+0

Ok, rozumiem. Myślałem, że to ponowne wykorzystanie obiektu dla tego samego przedmiotu, a nie dla innych. Jednak pasek przewijania staje się coraz większy podczas przewijania, w zależności od wysokości aktualnie wyświetlanego elementu. –

+0

@Arhimed Czy możesz wyjaśnić bardziej szczegółowo część "Wyjaśnienie". Utknąłem z tym problemem przez długi czas. – AbhishekB

+1

@abhishekb: sprawdź szczegóły - http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/ –

0

Sugestia - dodaj instrukcję dziennika po title.setText i wpisz wartość uzyskaną z getTitle(). Możesz dowiedzieć się, dlaczego dostajesz zduplikowane wpisy.

2

ListView nie gwarantuje niepowtarzalności elementów, które zostały tam dodane. To twoja odpowiedzialność. Używasz ArrayList do przechowywania przedmiotów i możesz przechowywać tyle duplikatów, ile chcesz.

Jeśli chcesz usuwa duplikaty umieścić swoje pozycje w zestawie, a następnie na liście ponownie:

listMessages = new ArrayList<Messages>(new LinkedHashSet<Message>(listMessages))

LinkedHashSet usunie duplikaty zachowując początkową kolejność elementów, ArrayList pozwoli elementy dojazd pozycji.

4
public View getView(int position, View convertView, ViewGroup parent) { 
    LayoutInflater inflater = (LayoutInflater) context 
     .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    View gridView; 
    if (convertView == null) { 
     gridView = new View(context); 
    } else { 
     gridView = (View) convertView; 
    } 
    gridView = inflater.inflate(R.layout.worker_listmain, null); 
    // your source code here!!! Run 100% 
    // I got this problem also, I found out the way to solve it! 
    // Please use my source code :D SIMPLE is PERFECT :D 
    return gridView; 
}