为什么ListView没有从适配器更新?

时间:2014-03-07 16:05:53

标签: android listview adapter

这是我的活动:

public class Messaging extends Activity implements OnItemClickListener {

ListView lstv;
MessagingAdapter listAdapter;
List<Generic4lstv> rowItems = new ArrayList<Generic4lstv>();


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_messaging);

    // lstv
    lstv = (ListView) findViewById(R.id.lstv_mess);
    lstv.setOnItemClickListener(this);
    listAdapter = new MessagingAdapter(this, rowItems);
    lstv.setAdapter(listAdapter);

    fillListview();
}

//***the trick
private final int interval = 200; // 1 Second
private Handler handler = new Handler();
private Runnable runnable = new Runnable(){
    public void run() {
        listAdapter.notifyDataSetChanged();
    }
};

public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {

    if (!rowItems.get(arg2).getIsSelected()) {
        Log.w("wwwwwww", "in");
        rowItems.get(arg2).setIsSelected(true);

        //call the ***trick
        handler.postDelayed(runnable, interval);
    }
}

我的适配器:

public class MessagingAdapter extends BaseAdapter {

private List<Generic4lstv> data;
private Context context;

public MessagingAdapter(Context context, List<Generic4lstv> items) {
    this.context = context;
    this.data = items;
}

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

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

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

@Override
public View getView(int position, View convertView, ViewGroup arg2) {

    View row = convertView;
    ViewHolder holder;

    if (row == null) {
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        row = inflater.inflate(R.layout.activity_messaging_row, arg2, false);

        holder = new ViewHolder();

        holder.rowText = (TextView) row.findViewById(R.id.titleTextView);
        holder.rowDate = (TextView) row.findViewById(R.id.dateTextView);
        holder.rowImage = (ImageView) row.findViewById(R.id.mailIcon);

        // store the holder with the view.
        row.setTag(holder);

    } else {
        // we've just avoided calling findViewById() on resource everytime
        // just use the viewHolder
        holder = (ViewHolder) row.getTag();
    }


    Generic4lstv item = (Generic4lstv) getItem(position);

    if (item == null) {
        Log.w("wwwwwww", "isnull!!!");
    } else {
        holder.rowText.setText(item.getRowText());
        holder.rowDate.setText(item.getRowTextDate());

        if (item.getIsSelected()) { // aka is red
            Log.w("wwwwwww", "IsSelected" + item.getRowID());
            holder.rowText.setTextColor(Color.GRAY);
            holder.rowImage.setImageResource(R.drawable.mail);
        } else {
            Log.w("wwwwwww", "Is NOT Selected" + item.getRowID());
            holder.rowText.setTextColor(Color.BLACK);
            holder.rowImage.setImageResource(R.drawable.mail_new);
        }
    }

    return row;
}

static class ViewHolder {
    ImageView rowImage;
    TextView rowText;
    TextView rowDate;
}

}

正如您所看到的,在Activity onItemClick 事件中,我调用了一个执行适配器notifyDataSetChanged的runnable,一切正常,但是如果我执行 listAdapter.notifyDataSetChanged(); rowItems.get(arg2).setIsSelected(true); 之后,UI没有更新!!

在我花了2小时之后创建了Runnable,最后我把它改为: https://stackoverflow.com/a/19074462/1320686

有人可以提供更好的方式,或者我在代码中做错了什么?

1 个答案:

答案 0 :(得分:1)

我想您的代码中有一些内容会使列表变慢。我刚刚创建了一个新项目,我在setIsSelected(true)之后调用了notifyDataSetChanged();它工作正常。也许问题出在你的fillListView()方法上。您可以在不同的项目中尝试我的代码,看看它是如何工作的,以及两个项目之间的区别。

我的活动

  import android.app.Activity;
  import android.os.Bundle;
  import android.view.View;
  import android.widget.AdapterView;
  import android.widget.ListView;
  import java.util.ArrayList;

public class MainActivity extends Activity implements AdapterView.OnItemClickListener {

private ArrayList<Item> mItemArrayList;
private MyCustomAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mItemArrayList = new ArrayList<Item>();

    //for simplicity we will add the same name for 20 times to populate the mItemArrayList view
    for (int i = 0; i < 20; i++) {
        Item item = new Item();
        item.setName("Laura" + i);
        mItemArrayList.add(item);
    }

    //relate the listView from java to the one created in xml
    ListView myListView = (ListView) findViewById(R.id.list);

    //show the ListView on the screen
    // The adapter MyCustomAdapter is responsible for maintaining the data backing this mItemArrayList and for producing
    // a view to represent an item in that data set.
    adapter = new MyCustomAdapter(MainActivity.this, mItemArrayList);
    myListView.setOnItemClickListener(this);
    myListView.setAdapter(adapter);
}  

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    if (!mItemArrayList.get(position).isSelected()) {
        mItemArrayList.get(position).setSelected(true);
        adapter.notifyDataSetChanged();
    }
  }
}

我的自定义适配器

   package ex.list.list;
   import android.content.Context;
   import android.graphics.Color;
   import android.view.LayoutInflater;
   import android.view.View;
   import android.view.ViewGroup;
   import android.widget.BaseAdapter;
   import android.widget.TextView;
   import java.util.ArrayList;

public class MyCustomAdapter extends BaseAdapter {
private ArrayList<Item> mListItems;
private LayoutInflater mLayoutInflater;

public MyCustomAdapter(Context context, ArrayList<Item> arrayList){

    mListItems = arrayList;

    //get the layout inflater
    mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    //getCount() represents how many items are in the mItemArrayList
    return mListItems.size();
}

@Override
//get the data of an item from a specific position
//i represents the position of the item in the mItemArrayList
public Object getItem(int position) {
    return mListItems.get(position);
}

@Override
//get the position id of the item from the mItemArrayList
public long getItemId(int i) {
    return 0;
}

@Override
public View getView(int position, View view, ViewGroup viewGroup) {

    // create a ViewHolder reference
    ViewHolder holder;

    //check to see if the reused view is null or not, if is not null then reuse it
    if (view == null) {
        holder = new ViewHolder();

        view = mLayoutInflater.inflate(R.layout.list_item, null);
        holder.itemName = (TextView) view.findViewById(R.id.list_item_text_view);

        // the setTag is used to store the data within this view
        view.setTag(holder);
    } else {
        // the getTag returns the viewHolder object set as a tag to the view
        holder = (ViewHolder)view.getTag();
    }

    Item item = (Item) getItem(position);
    if (item != null) {
        if (holder.itemName != null) {
            //set the item name on the TextView
            holder.itemName.setText(item.getName());
        }

        if (item.isSelected()){
            holder.itemName.setTextColor(Color.RED);
        } else {
            holder.itemName.setTextColor(Color.WHITE);
        }
    }

    //this method must return the view corresponding to the data at the specified position.
    return view;
}

/**
 * Static class used to avoid the calling of "findViewById" every time the getView() method is called,
 * because this can impact to your application performance when your mItemArrayList is too big. The class is static so it
 * cache all the things inside once it's created.
 */
private static class ViewHolder {
    protected TextView itemName;
 }
 }

项目对象

public class Item {
private boolean isSelected;
private String name;

public boolean isSelected() {
    return isSelected;
}

public void setSelected(boolean isSelected) {
    this.isSelected = isSelected;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
  }
}

<强> activity_main.xml中

<?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">
<ListView android:id="@+id/list"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:transcriptMode="alwaysScroll"
          android:cacheColorHint="#00000000"
          android:listSelector="@android:color/transparent"/>
 </LinearLayout>

<强> list_item.xml

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

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/list_item"
android:gravity="center_vertical">


<TextView android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:id="@+id/list_item_text_view"
          android:textSize="20sp"
          android:padding="10dp"
          android:layout_marginLeft="5dp"/>

</LinearLayout>