繁体   English   中英

使用自定义适配器刷新ListView

[英]Refreshing a ListView with a custom adapter

我正在为Android编写一个小型的Google Talk客户端,并且无法正确刷新ListView。

此列表包含联系人列表,并显示联系人的姓名和状态。 我的侦听器工作正常,并且可以在日志猫窗口中看到每个联系人的状态更改,但是我的ListView没有刷新...这是一些代码:

package de.marc.messenger;

// ofc here are the imports

public class RosterActivity extends Activity {

private Roster _roster;
private XMPPConnection _connection;
private List<HashMap<String, String>> _buddies;
private BuddyAdapter _adapter;
private ListView _list;

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

    _buddies = new ArrayList<HashMap<String, String>>();
    _connection = LoginActivity.CONNECTION;

    makePauseForRoster();

    _roster = _connection.getRoster();

    addRosterListener();
    fillBuddyList();
    sortBuddyList();
    initializeListView();
}

/**
 * Lets the thread sleep for a second to ensure that the presence of every
 * user will be available
 */
private void makePauseForRoster() {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

/**
 * Adds a listener to the roster, primarily for changes of presence
 */
private void addRosterListener() {
    _roster.addRosterListener(new RosterListener() {
        public void presenceChanged(Presence presence) {
            String user = presence.getFrom().split("/")[0];
            HashMap<String, String> buddy = findBuddyInRoster(user);
            String p = getPresenceString(user);
            buddy.put("presence", p);
            System.out.println(buddy.values().toString()); // this works
            _adapter.notifyDataSetChanged(); // this doesn't
            _list.invalidate(); // this neither
        }
    });
}

/**
 * Fills the list view with the roster entries
 */
private void initializeListView() {

    _adapter = new BuddyAdapter(this, R.layout.roster_item,
            _buddies);

    _list = (ListView) findViewById(R.id.list_roster);
    _list.setAdapter(_adapter);
}

/**
 * Fills the buddy list with relevant data from a RosterEntry. Relevant data
 * is the users' name, email and presence
 */
private void fillBuddyList() {
    // this just fills my list of hashmaps (_buddies)
}

/**
 * Get a predefined String depending on the presence of a user
 */
private String getPresenceString(String user) {
    // something like "available: away ()" -> "away"
}

/**
 * Sorts the buddy list. Only criterion is the presence of the user, because
 * we have linear algorithms for this kind of problem.
 */
private void sortBuddyList() {
    // move all offline contacts to the end
    // move all online contacts to the beginning
    // all other kind of contacts will stay in the middle
}

/**
 * Finds a specific buddy object for a user via his hashed email
 */
private HashMap<String, String> findBuddyInRoster(String user) {
    for (HashMap<String, String> buddy : _buddies) {
        if (user.equals(buddy.get("user"))) {
            return buddy;
        }
    }
    return null;
}

}

这可以正常工作,一切都可以正确显示。.唯一的麻烦似乎是在实现onPresenceChanged()的addRosterListener()方法中。

这是我的适配器:

package de.marc.messenger;

// as well some imports

public class BuddyAdapter extends ArrayAdapter<HashMap<String, String>> {

private Context _context;
private List<HashMap<String, String>> _map;
    private LayoutInflater _inflater;

public BuddyAdapter(Context context, int id, List<HashMap<String, String>> map) {
    super(context, id, map);
    _context = context;
    _map = map;
            _inflater = (LayoutInflater) _context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

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

    // find view of a single row in a listview
    View row = convertView;
    if (convertView == null) {
        row = _inflater.inflate(R.layout.roster_item, null);
    }

    // get data for a specific row
    String name = _map.get(position).get("name");
    String user = _map.get(position).get("user");
    String presence = _map.get(position).get("presence");

    // extract views from the row view
    TextView nameText = (TextView) row.findViewById(R.id.text_name);
    TextView userText = (TextView) row.findViewById(R.id.text_id);
    ImageView presenceImg = (ImageView) row
            .findViewById(R.id.image_presence);

    // set data in extracted views
    nameText.setText(name);
    userText.setText(user);

    int resource = 0;
    // something is done with this variable
    presenceImg.setImageResource(resource);

    return row;
}

}

我有什么想念的吗?

编辑:我这样更改了onPresenceChanged方法:

public void presenceChanged(Presence presence) {
    String user = presence.getFrom().split("/")[0];
    HashMap<String, String> buddy = findBuddyInRoster(user);
    _adapter.remove(buddy);
    String p = getPresenceString(user);
    buddy.put("presence", p);
    _adapter.add(buddy);
    _adapter.notifyDataSetChanged();
}

它在某种程度上有效:在屏幕上滑动了一点之后,更改了他的状态的联系人现在不在列表中:/

构造ArrayAdapter时,它保留传入的List的引用。如果要传入作为Activity成员的List,并在以后更改该Activity成员,则ArrayAdapter仍然持有对List的引用。原始清单。 适配器不知道您更改了活动列表。

在我看来,这就是您的工作,因此您需要使用新的列表数据重新创建适配器。

或者,您可以使用ArrayAdapter方法来修改基础List( addinsertremoveclear等),然后notifyDataSetChanged将起作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM