Android 如何更有效地做到这一点?(列表适配器)

Android 如何更有效地做到这一点?(列表适配器),android,list,performance,Android,List,Performance,我有一个列表,每个条目都有一个应该显示的属性的动态计数。行中的每个属性都有一个名称和一个值。这个实现是有效的,但是我如何才能以更有效的方式实现呢?到现在为止,我需要在非常耗时的事情之前建立整个列表/地图…: // get category names Map<Long, String> categoriesNames = new HashMap<Long, String>(); // ... // create log-list of m

我有一个列表,每个条目都有一个应该显示的属性的动态计数。行中的每个属性都有一个名称和一个值。这个实现是有效的,但是我如何才能以更有效的方式实现呢?到现在为止,我需要在非常耗时的事情之前建立整个列表/地图…:

    // get category names
    Map<Long, String> categoriesNames = new HashMap<Long, String>();
    // ...

    // create log-list of maps for SimpleAdapter
    List<Map<String, String>> logsMap = new ArrayList<Map<String, String>>();
    // getAll() is just: db.query(true, TABLE_NAME, null, null, null, null, null, Columns.TIMESTAMP + " desc", null);
    Cursor logs = logDao.getAll();
    try {
        int idIndex = logs.getColumnIndex("_id");
        int timestampIndex = logs.getColumnIndex("timestamp");
        int categoryIdIndex = logs.getColumnIndex("category_id");
        int noteIndex = logs.getColumnIndex("note");
        while (logs.moveToNext()) {
            Map<String, String> map = new HashMap<String, String>();
            map.put("category", categoriesNames.get(logs.getLong(categoryIdIndex)));
            map.put("note", getString(R.string.note) + ": " + logs.getString(noteIndex));
            map.put("timestamp", MyDateUtils.formatDateTime(logs.getLong(timestampIndex)));
            map.put("attributes", attributeLogDao.getAttributesAndValuesByLogId(logs.getLong(idIndex)));
            logsMap.add(map);
        }
    } finally {
        logs.close();
    }

    // Mapping
    String[] from = new String[] { "category", "note", "timestamp", "attributes" };
    int[] to = new int[] {
            R.id.log_list_row_category, R.id.log_list_row_note,
            R.id.log_list_row_datetime, R.id.log_list_row_attributes };

    // ListView Adapter
    SimpleAdapter simpleAdapter = new SimpleAdapter(this,
            logsMap, R.layout.log_list_row, from, to);
    ListView lv = (ListView) this.findViewById(R.id.listView);
    lv.setAdapter(simpleAdapter);
(几乎是while循环中的最后一行)

这个电话的作用是:

public String getAttributesAndValuesByLogId(long logId) {
    String attributesString = "";
    Cursor c = db.getSQLiteDatabase().rawQuery("SELECT al." + Columns.VALUE + " AS value, a." + AttributeDao.Columns.NAME + " AS a_name" +
            " FROM " + TABLE_NAME + " AS al, " + AttributeDao.TABLE_NAME + " AS a" +
            " WHERE al." + Columns.LOG_ID + " = " + logId +
            " AND a." + AttributeDao.Columns.ID + " = al." + Columns.ATTRIBUTE_ID +
            " ORDER BY value DESC", null);
    if (c != null && c.moveToFirst()) {
        do {
            attributesString += c.getString(1) + " (" + c.getLong(0) + ")\n";
        } while (c.moveToNext());
        c.close();
    }
    return attributesString;
}

谢谢

为您指明写入方向:

  • 使用
    SimpleCursorAdapter
    ,保留大部分代码不变
  • 实现需要一个方法的
    SimpleCursorAdapter.ViewBinder
  • setViewValue
    的实现将与
    while
    循环的当前主体几乎相同
  • 使用
    SimpleCursorAdapter\setViewBinder
    将两者链接起来
视图绑定器的目的是让您有机会自定义列如何影响它们绑定到的行。
setViewValue
的实现如下所示:

if (columnIndex == categoryIdIndex) {
    ... populate view with category name ...
    return true;
}
if (columnIndex == timestampIndex) {
    ...

谢谢这很有效。现在唯一的问题是列表本身的滚动是不平稳的,因为在每个“setViewValue”中都需要调用attributeLogDao.getAttributesAndValuesByLogId(logs.getLong(idIndex))。。。但无论如何,这比开始时长时间加载要好…你能通过连接获得属性吗?(我假设您的getAttributes…方法正在进行额外的数据库查询。)
if (columnIndex == categoryIdIndex) {
    ... populate view with category name ...
    return true;
}
if (columnIndex == timestampIndex) {
    ...