Android ListView 适配器加载错误

Posted

技术标签:

【中文标题】Android ListView 适配器加载错误【英文标题】:Android ListView adapter loads wrong 【发布时间】:2014-04-18 11:24:04 【问题描述】:

由于某种原因,当我使用此代码时,它无法正常工作。它不是将每个十字路口放在它的位置上,而是将最后一个放在第一个十字路口,其余的都是空的。

package com.Itay.lightalaram.lightalarm;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

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

public class Cros-s-roadsActivity extends Activity 
    private List<Cros-s-road> cros-s-roads;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.cros-s-roads);

        cros-s-roads = new ArrayList<Cros-s-road>();

        populateListView();
    

    private void populateListView() 
        ListView list = (ListView) findViewById(R.id.cros-s-roadsListView);
        cros-s-roads.add(new Cros-s-road("Oranim", 50, 30));
        cros-s-roads.add(new Cros-s-road("Evelina", 40, 85));
        cros-s-roads.add(new Cros-s-road("Sacker", 43, 22));
        cros-s-roads.add(new Cros-s-road("bagger", 43, 22));


        ArrayAdapter<Cros-s-road> adapter = new Cros-s-roadAdapter();

        list.setAdapter(adapter);
    

    private class Cros-s-roadAdapter extends ArrayAdapter<Cros-s-road> 
        public Cros-s-roadAdapter()
            super(Cros-s-roadsActivity.this, R.layout.item_cros-s-road, cros-s-roads);
        

        @Override
        public View getView(int position, View convertView, ViewGroup parent) 
            View itemView = convertView;
            if(null == itemView) 
                itemView = getLayoutInflater().inflate(R.layout.item_cros-s-road, parent, false);

                Cros-s-road currentCros-s-road = cros-s-roads.get(position);

                TextView name = (TextView) findViewById(R.id.item_cros-s-roadName);
                TextView redLight = (TextView) findViewById(R.id.item_redLightDuration);
                TextView greenLight = (TextView) findViewById(R.id.item_greenLightDuration);
                try 
                    name.setText(currentCros-s-road.getName());
                    redLight.setText("" + currentCros-s-road.getRedLight());
                    greenLight.setText("" + currentCros-s-road.getGreenLight());
                 catch (Exception e) 
                
                return itemView;
            
            return null;
        
    

输出:

【问题讨论】:

从您的 Adapter 中删除 return null; 我用ViewHolder 模式更新了我的答案。你应该看看。编码愉快。 【参考方案1】:

说明 出现此问题的原因是您只设置了一次膨胀布局,此时 convertView 的条件为 null。但是,在第一次itemView 之后,就不是null。除了第一个之外,您的项目没有更新。此外,您需要返回列表项的所有视图 (itemView)。

解决方案 在您的适配器中,getView 方法需要扩展一个布局(once)并返回此布局:

// inflate the layout to the row (items)
View itemView = convertView;
if(null == itemView) 
    itemView = getLayoutInflater().inflate(R.layout.item_cros-s-road, parent, false);

// Then return the inflated view and all its stuff
return itemView;

此外,您需要将所有项目的视图附加到布局,如下所示:

 // itemView.findViewById(...) to retrieve the id which is on the inflated layout
 TextView name = (TextView) itemView.findViewById(R.id.item_cros-s-roadName);

最后,为了提高Adapter 的性能,您应该使用ViewHolder。这将避免您永远调用所有 findViewById 方法。这是great tutorial 和a simple example。那么,你的方法可能是:

 // Init your variables
 public ViewHolder 
     TextView name, redLight, greenLight
 

 @Override
 public View getView(int position, View convertView, ViewGroup parent) 
      View itemView = convertView;
      // create the ViewHolder variable
      ViewHolderItem viewHolder;

      if(itemView == null) 
           itemView = getLayoutInflater().inflate(R.layout.item_cros-s-road, parent, false);

           // create a new ViewHolder
           viewHolder = new ViewHolderItem();

           // get your views with the ViewHolder and attached to the inflated layout
           viewHolder.name = (TextView) itemView.findViewById(R.id.item_cros-s-roadName);
           viewHolder.redLight = (TextView) itemView.findViewById(R.id.item_redLightDuration);
           viewHolder.greenLight = (TextView) itemView.findViewById(R.id.item_greenLightDuration);

           // store the ViewHolder
           itemView.setTag(viewHolder);
     else
         // this is not the first, reuse the stored ViewHolder
         viewHolder = (ViewHolderItem) convertView.getTag();
     

     // do your stuff...
     Cros-s-road currentCros-s-road = cros-s-roads.get(position);
     try 
         viewHolder.name.setText(currentCros-s-road.getName());
         viewHolder.redLight.setText("" + currentCros-s-road.getRedLight());
         viewHolder.greenLight.setText("" + currentCros-s-road.getGreenLight());
      catch (Exception e)  

     // return the layout inflated
     return itemView;
  

【讨论】:

【参考方案2】:
 private class Cros-s-roadAdapter extends ArrayAdapter<Cros-s-road> 
    public Cros-s-roadAdapter() 
        super(MainActivity.this, R.layout.item_cros-s-road, cros-s-roads);
    

    TextView name, redLight, greenLight;

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        View itemView = convertView;
        Cros-s-road currentCros-s-road = cros-s-roads.get(position);
        if (null == itemView) 
            itemView = getLayoutInflater().inflate(R.layout.item_cros-s-road,
                    parent, false);

            name = (TextView) itemView
                    .findViewById(R.id.item_cros-s-roadName);
            redLight = (TextView) itemView
                    .findViewById(R.id.item_redLightDuration);
            greenLight = (TextView) itemView
                    .findViewById(R.id.item_greenLightDuration);

        
        try 
            name.setText(currentCros-s-road.getName());
            redLight.setText("" + currentCros-s-road.getRedLight());
            greenLight.setText("" + currentCros-s-road.getGreenLight());
         catch (Exception e) 
        
        return itemView;
    

【讨论】:

我不认为这是一个正确的答案:第一个文本视图没有附加到膨胀的布局上。第二个更多的内容和解释将非常感激。谢谢。【参考方案3】:

将getview方法改为

public View getView(int position, View convertView, ViewGroup parent) 
View itemView = convertView;
if(null == itemView) 
    itemView = getLayoutInflater().inflate(R.layout.item_cros-s-road, parent, false);

    Cros-s-road currentCros-s-road = cros-s-roads.get(position);

    TextView name = (TextView) itemView.findViewById(R.id.item_cros-s-roadName);
    TextView redLight = (TextView) itemView.findViewById(R.id.item_redLightDuration);
    TextView greenLight = (TextView) itemView.findViewById(R.id.item_greenLightDuration);

    name.setText(currentCros-s-road.getName());
    redLight.setText("" + currentCros-s-road.getRedLight());
    greenLight.setText("" + currentCros-s-road.getGreenLight());

    return itemView;         

评论我的结果

【讨论】:

以上是关于Android ListView 适配器加载错误的主要内容,如果未能解决你的问题,请参考以下文章

android listview 适配器 asynctask 图像加载

android从listview中删除任何项目删除最后一个元素

在android(初级)的Listview上延迟加载图像? [复制]

Android - ListView 在到达结束时加载更多项目[关闭]

如何清空android ListView控件的内容

将图像从 URL 加载到 ListView