2011-09-26 11 views
12

Mam jeden ListView i jeden BaseAdapter. Pobierałem produkty z usługi sieciowej i wyświetlałem na liście. Wyświetlane jest poprawnie na liście.Wyświetlanie kolejności wierszy w kolejności losowej w przewijaniu listy w Androidzie

Ale kiedy przewijam ListView wyświetla wiersze w losowej pozycji oznacza czasami wyświetlacz trzeciego rzędu na pierwszej pozycji, wiersz środkowy wyświetla pozycję na ostatniej pozycji i tak dalej.

To moja klasa adapter

public class ProductListAdapter extends BaseAdapter implements OnClickListener{ 

    LayoutInflater inflater; 
    ArrayList<Product> arrProducts; 
    Context c; 

    public ProductListAdapter(Context c, ArrayList<Product> arrProducts) { 
     super(); 
     inflater = LayoutInflater.from(c); 
     this.arrProducts = arrProducts; 
     this.c = c; 
    } 

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

    @Override 
    public Object getItem(int position) { 
     return arrProducts.get(position); 
    } 

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

    @Override 
    public View getView(int position, View v, ViewGroup parent) { 
     Product product = null; 
     if(v == null) { 
      v = inflater.inflate(R.layout.product_listview_row, null); 
      product = (Product) getItem(position); 
      v.setTag(product); 
     }else { 
      product = (Product)v.getTag(); 
     } 

     v.setOnClickListener(this); 

     TextView tvProductname = (TextView)v.findViewById(R.id.tvProductname); 
     tvProductname.setText(product.getTitle()); 

     String strReviewCount = product.getReviews(); 
     TextView tvReviewsCounts = (TextView)v.findViewById(R.id.tvReviews); 
     if(strReviewCount != null) tvReviewsCounts.setText(strReviewCount +" Reviews"); 

     Button btnPrice = (Button)v.findViewById(R.id.btnPrice); 
     btnPrice.setText(product.getSellingPrice()); 

     return v; 
    } 

    @Override 
    public void onClick(View v) { 
     Product product = (Product) v.getTag(); 
     Intent i = new Intent(c, ProductDetails.class); 
     i.putExtra(Product.PROD_ID, product.getId()); 
     startActivity(i); 
    } 

    @Override 
    public int getItemViewType(int position) { 
     return super.getItemViewType(position); 
    } 

    @Override 
    public int getViewTypeCount() { 
     return super.getViewTypeCount(); 
    } 
} 

To ListView na układ XML

<ListView android:id="@+id/lstProducts" style="@style/fill_parent" 
     android:dividerHeight="1dp" android:divider="#dbd3c5" 
     android:scrollbars="vertical" android:layout_below="@id/layLine"></ListView> 

także przy zmianie getView() metodę BaseAdapter tak to działa dobrze

@Override 
    public View getView(int position, View v, ViewGroup parent) { 
     Product product = null; 
     v = inflater.inflate(R.layout.product_listview_row, null); 
     product = (Product) getItem(position); 
     v.setTag(product); 
     v.setOnClickListener(this); 

     TextView tvProductname = (TextView)v.findViewById(R.id.tvProductname); 
     tvProductname.setText(product.getTitle()); 

     String strReviewCount = product.getReviews(); 
     TextView tvReviewsCounts = (TextView)v.findViewById(R.id.tvReviews); 
     if(strReviewCount != null) tvReviewsCounts.setText(strReviewCount +" Reviews"); 

     Button btnPrice = (Button)v.findViewById(R.id.btnPrice); 
     btnPrice.setText(product.getSellingPrice()); 

     return v; 
    } 

Ale problem w tego typu jestem wyświetlając obraz produktu na listview rzędu które nie uznają here.By korzystania z tego typu kodu getView() metoda zawsze Utwórz nowy widok, gdy kiedykolwiek zwój ListView tak, że muszę pobierz obraz ponownie. Używałem klasy ImageLoader, która używa obrazów cash memory do pobierania obrazów, ale problem polega na tym, że po wielokrotnym ustawieniu obrazu na ImageView daje mi to out of memory error.

Proszę, pomóż mi rozwiązać ten problem.

Dzięki

Odpowiedz

10

wylądowałem tutaj z powodu linkiem do roztworu prawo.

Problem polega na tym, że wiążesz produkt raz z widokiem podczas tworzenia nowego widoku. należy zgłosić to na każdym wywołaniu getView:

product = (Product) getItem(position); 
v.setTag(product); 

Ale można nazwać v.setOnClickListener(this) po utworzeniu widoku (nie zmieni się w każdym razie).

To powinno wystarczyć. Implementacja typu widoku jest właśnie tutaj nadużywana. Polecam przeczytać my answer here ...

+0

Wiem, że moja odpowiedź nie była dokładna droga do wykorzystania ale tymczasowy celem zarządzałem przy użyciu typu widoku. Mam nadzieję, że twoje rozwiązanie działa i zostanie sprawdzone. –

+0

Dziękuję. Mam nadzieję, że nie poczujecie się urażeni, to nie była moja intencja. Problem polegał na tym, że ludzie akceptują * sztuczkę * jako normalną i działającą, a następnie stają się naprawdę zdezorientowani, gdy coś pójdzie nie tak później lub gdy chcą zastosować realną implementację typu widoku ... Chciałem tylko, żeby było jasne, zamiast rozpoczynać plotki; -) – Knickedi

+0

Nie, nie, to jest dobre dla mnie, aby uzyskać dokładne rozwiązanie. Osobiście uważam, że twoja odpowiedź na pewno zadziała, a ja też ją wypróbuję. I uczucie złego nigdy nie jest przypadkiem, jestem tu także, aby się uczyć. To ma coś nowego od ciebie. Dzięki. –

5

Dlatego według recommendations wykonane przez Knickedi metoda getView() powinna wyglądać następująco:

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

    TextView tvProductname; 
    TextView tvReviewsCounts; 
    Button btnPrice; 

    // Phase 1... 
    if (v == null) { 
     v = inflater.inflate(R.layout.product_listview_row, null); 
     v.setOnClickListener(this); 

     tvProductname = (TextView)v.findViewById(R.id.tvProductname); 
     tvReviewsCounts = (TextView)v.findViewById(R.id.tvReviews); 
     btnPrice = (Button)v.findViewById(R.id.btnPrice); 

     v.setTag(R.id.tvProductname, tvProductname); 
     v.setTag(R.id.tvReviews, tvReviewsCounts); 
     v.setTag(R.id.btnPrice, btnPrice); 
    } 
    else { 
     tvProductname = (TextView) v.getTag(R.id.tvProductname); 
     tvReviewsCounts = (TextView) v.getTag(R.id.tvReviews); 
     btnPrice = (Button) v.getTag(R.id.btnPrice); 
    } 

    // Phase 2... 
    Product product = (Product) getItem(position); 

    tvProductname.setText(product.getTitle()); 
    btnPrice.setText(product.getSellingPrice()); 

    String strReviewCount = product.getReviews(); 
    if(strReviewCount != null) 
     tvReviewsCounts.setText(strReviewCount +" Reviews"); 

    return v; 
} 
+0

Zachowaj ostrożność 'public void setTag (int, tag Object)' został dodany na poziomie API 4 ... – eightyfive

Powiązane problemy