行在ListView中重复

时间:2012-03-26 15:57:57

标签: android listview

我知道这个问题出现了很多次,但由于某种原因,我似乎无法让它发挥作用。 在某些情况下,getView被多次调用的事实。

但是,在此处给出的示例中:http://android.amberfog.com/?p=296 它表示对数据中每一行的第一次调用应该在currentView中得到一个空值。 这种情况没有发生。

对我来说,当position为0时的调用将currentView设置为null,而position为1的调用将currentView设置为现有对象。

总共有16次调用“getView”但我得到的行重复一次(即每行两次)。 第0行 第1行 第0行 第1行

我可能只是从那篇文章中听不懂。

布局:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"   
    android:layout_height="fill_parent"
    >
    <TextView android:id="@+id/title_paired_devices" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/title_paired_devices" 
        android:visibility="gone"
        android:background="#666"
        android:textColor="#fff"
        android:paddingLeft="5dp"
    />
    <ListView android:id="@+id/paired_devices"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:stackFromBottom="true"
        android:layout_weight="1"
    />
    <TextView android:id="@+id/title_new_devices"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/title_other_devices"
        android:visibility="gone"
        android:background="#666"
        android:textColor="#fff"
        android:paddingLeft="5dp"
    />
    <ListView android:id="@+id/new_devices"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:stackFromBottom="true"
        android:layout_weight="2"
    />
    <Button android:id="@+id/button_scan" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/button_scan"
    />
</LinearLayout>

Listview行:

    <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.

android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/list_selector"
    android:orientation="horizontal"
    android:padding="5dip" >

    <!--  ListRow Left side Thumbnail image -->
    <LinearLayout android:id="@+id/thumbnail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="3dip"
        android:layout_alignParentLeft="true"
        android:background="@drawable/image_bg"
        android:layout_marginRight="5dip">

        <ImageView
            android:id="@+id/list_image"
            android:layout_width="50dip"
            android:layout_height="50dip"
            android:src="@drawable/icon"/>

    </LinearLayout>

    <!-- Device Address -->
    <TextView
        android:id="@+id/tvwDeviceAddress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/thumbnail"
        android:layout_toRightOf="@+id/thumbnail"
        android:textColor="#040404"
        android:typeface="sans"
        android:textSize="15dip"
        android:textStyle="bold"/>

    <!-- Display Name -->
    <TextView
        android:id="@+id/tvwDisplayName"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tvwDeviceAddress"
        android:textColor="#343434"
        android:textSize="10dip"
        android:layout_marginTop="1dip"
        android:layout_toRightOf="@+id/thumbnail"/>


</RelativeLayout>

适配器:

    private class LazyAdapter extends BaseAdapter {

    private Activity activity;
    private ArrayList<MPGDeviceDetails> data;
    private LayoutInflater inflater=null;

    public LazyAdapter(Activity a, ArrayList<MPGDeviceDetails> d) {
        activity = a;
        data=d;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public int getCount() {
        return data.size();
    }

    public Object getItem(int position) {
        return position;
    }

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

    public View getView(int position, View convertView, ViewGroup parent) {
        View vi=convertView;
        Log.e("MPG","Position = " + position + ".  ConvertView = " + convertView);
        if(convertView==null)
            vi = inflater.inflate(R.layout.device_name, null);

        TextView address = (TextView)vi.findViewById(R.id.tvwDeviceAddress); // Device Address
        TextView name = (TextView)vi.findViewById(R.id.tvwDisplayName); // Display name
        ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // thumb image



        address.setText(data.get(position).deviceAddress);
        name.setText(data.get(position).getDisplayName());
        Bitmap photo = data.get(position).getContactPhoto();
        if (photo != null)
            thumb_image.setImageBitmap(photo);


        return vi;
    }
}

用法:

    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Setup the window
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    setContentView(R.layout.device_list);

    // Set result CANCELED incase the user backs out
    setResult(Activity.RESULT_CANCELED);

    // Initialize the button to perform device discovery
    Button scanButton = (Button) findViewById(R.id.button_scan);
    scanButton.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            doDiscovery();
            v.setVisibility(View.GONE);
        }
    });

    // Initialize array adapters. One for already paired devices and
    // one for newly discovered devices


    // Find and set up the ListView for paired devices
    pairedListView = (ListView) findViewById(R.id.paired_devices);
    pairedDevicesList = new ArrayList<MPGDeviceDetails>();
    pairedListView.setAdapter((mPairedDevicesArrayAdapter = new LazyAdapter(this,pairedDevicesList)));
    pairedListView.setOnItemClickListener(mDeviceClickListener);
    registerForContextMenu(pairedListView);

    // Get the local Bluetooth adapter
    mBtAdapter = BluetoothAdapter.getDefaultAdapter();

    // Get a set of currently paired devices
    Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();

    // If there are paired devices, add each one to the ArrayAdapter
    if (pairedDevices.size() > 0) {
        findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
        for (BluetoothDevice device : pairedDevices) {
          pairedDevicesList.add(MPGDeviceDetailsControl.getDeviceDetails(this, device.getAddress(), device.getName()));
        }
    } 

}

MPGDeviceDetails是一个保存特定设备的所有数据的对象。

这是“debug”命令的输出:

03-27 10:03:30.730: E/MPG(2841): Position = 0.  ConvertView = null.
03-27 10:03:30.742: E/MPG(2841): Position = 1.  ConvertView = android.widget.RelativeLayout@4062d608. 
03-27 10:03:30.746: E/MPG(2841): Position = 0.  ConvertView = null. 
03-27 10:03:30.750: E/MPG(2841): Position = 1.  ConvertView = android.widget.RelativeLayout@40628d78. 
03-27 10:03:30.750: E/MPG(2841): Position = 0.  ConvertView = android.widget.RelativeLayout@4062d608. 
03-27 10:03:30.753: E/MPG(2841): Position = 1.  ConvertView = android.widget.RelativeLayout@4062d608. 
03-27 10:03:30.753: E/MPG(2841): Position = 0.  ConvertView = android.widget.RelativeLayout@40628d78. 
03-27 10:03:30.753: E/MPG(2841): Position = 1.  ConvertView = android.widget.RelativeLayout@40628d78. 
03-27 10:03:30.761: E/MPG(2841): Position = 1.  ConvertView = android.widget.RelativeLayout@4062d608. 
03-27 10:03:30.761: E/MPG(2841): Position = 0.  ConvertView = null. 
03-27 10:03:30.769: E/MPG(2841): Position = 1.  ConvertView = android.widget.RelativeLayout@40628d78. 
03-27 10:03:30.769: E/MPG(2841): Position = 0.  ConvertView = null. 
03-27 10:03:30.777: E/MPG(2841): Position = 0.  ConvertView = null. 
03-27 10:03:30.781: E/MPG(2841): Position = 1.  ConvertView = android.widget.RelativeLayout@406d4af8. 
03-27 10:03:30.781: E/MPG(2841): Position = 0.  ConvertView = null. 
03-27 10:03:30.785: E/MPG(2841): Position = 1.  ConvertView = android.widget.RelativeLayout@40694970. 
03-27 10:03:30.789: E/MPG(2841): Position = 0.  ConvertView = android.widget.RelativeLayout@406d4af8. 
03-27 10:03:30.789: E/MPG(2841): Position = 1.  ConvertView = android.widget.RelativeLayout@406d4af8. 
03-27 10:03:30.789: E/MPG(2841): Position = 0.  ConvertView = android.widget.RelativeLayout@40694970. 
03-27 10:03:30.792: E/MPG(2841): Position = 1.  ConvertView = android.widget.RelativeLayout@40694970. 

这就是屏幕的样子: enter image description here

有趣的是,虽然所有4个按钮都有效,但上下文菜单仅适用于前两个按钮!

4 个答案:

答案 0 :(得分:2)

填写notifyDataSetChanged()后,请尝试在适配器上调用pairedDevicesList

if (pairedDevices.size() > 0) {
    findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
    for (BluetoothDevice device : pairedDevices) {
        pairedDevicesList.add(MPGDeviceDetailsControl.getDeviceDetails(this, device.getAddress(), device.getName()));
    }
}
((BaseAdapder)getListAdapter()).notifyDataSetChanged();

填写pairedDevicesList后创建适配器。

还尝试声明适配器的数据具有稳定的ID:

@Override
public boolean hasStableIds() {
    return true;
}

答案 1 :(得分:0)

一般情况下,除了对每个项目进行常规的getView调用之外,它还要调用大约3倍,因为它需要计算滚动条大小,布局等视图的测量值。关于重复行,我认为你应该粘贴你的代码。你可能做错了什么。

有关详细信息,请查看this并阅读this

答案 2 :(得分:0)

currentView值应用于优化问题。 Android建议重用视图以节省内存并更快地响应。

当yor currentView不为null时,您可以使用它来显示当前项目 看看例子:

public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if (v == null) {
        // we can't reuse view and must read it from layout
        LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.whatever, null);
    }

   // ... use v as view for row
}

答案 3 :(得分:0)

在向其添加值之前,您只需要clear ArrayList。

此处为if条件

if (pairedDevices.size() > 0) { 
 pairedDevicesList.clear();
 // other code as it is
}

你也可以在清除ArrayList之前放一个日志。

Log.i("Size","ArrayList Size = "+pairedDevicesList.size());

所以你会得到更多的想法。