提高自定义 ArrayAdapter 和对象的性能

Improving performance on Custom ArrayAdapters and Objects

我一直在尝试学习如何通过使用 this tutorial 来制作自定义 ArrayAdapter 以在我的一些 Android 应用程序中使用,但对其进行了稍微调整以便我可以适应它与我自己的应用程序。

我已经在我的 phone 上测试了几次,但我发现性能速度非常慢(加载和滚动列表视图时)。不使用此自定义的其他活动 ArrayAdapter 具有正常的执行速度。

我不太确定问题可能是什么或我的代码中的什么地方,所以在下面,我发布了我所有的自定义 ArrayAdapter class:

package com.mycompany.myapp;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.util.ArrayList;

public class CustomArrayAdapter extends ArrayAdapter<String> {

    private static class ViewHolder {
        TextView tv_Id;
        TextView tv_Name;
        TextView tv_Group;
    }

    private Context context;
    private ArrayList<String> arr_items;

    public CustomArrayAdapter(Context context, ArrayList<String> arr_items) {
        super(context, R.layout.listview_advanced, arr_items);
        this.context = context;
        this.arr_items = arr_items;
    }

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

        // Get the data item for this position
        Person person = new Person(context, arr_items.get(position));

        // Check if an existing view is being reused, otherwise inflate the view
        ViewHolder viewHolder; // View lookup cache stored in tag
        if (convertView == null) {
            viewHolder = new ViewHolder();
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.listview_advanced, parent, false);
            viewHolder.tv_Id = (TextView) convertView.findViewById(R.id.lvAdv_text1);
            viewHolder.tv_Name = (TextView) convertView.findViewById(R.id.lvAdv_text2);
            viewHolder.tv_Group = (TextView) convertView.findViewById(R.id.lvAdv_text3);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        // Populate the data into the template view using the data object
        viewHolder.tv_Id.setText(person.getIDAsString());
        viewHolder.tv_Name.setText(person.getName());
        if (person.getGroup().equals("")) {
            viewHolder.tv_Group.setText("");
        } else {
            viewHolder.tv_Group.setText("(" + person.getGroup() + ")");
        }

        // Return the completed view to render on screen
        return convertView;
    }
}

如有任何帮助,我们将不胜感激。谢谢。

更新:

此外,在调用 CustomArrayAdapter 之前,我通过遍历 .csv 文件的行并获取该数据将数据添加到 ArrayList<String>。目前,在读取 .csv 文件时,我有这个:

...

ArrayList<String> arr_person = new ArrayList<>(); // Global variable

...

// In a method:
String data = inputStream.nextLine();
String[] line = data.split(",");
if (line.length >1) {
    arr_person.add(line[1]);
}

...

CustomArrayAdapter adapter = new CustomArrayAdapter(getActivity(), arr_person);
lv_main.setAdapter(adapter);

我如何将其调整为对象?

更新 2:

我的 Person 对象是这样工作的:

private Context context;
private String person, group, someAttribute, ... ;
private int idNumber, scoreOne, scoreTwo, scoreThree, scoreFour, scoreFive, scoreSix, scoreTotal, ... ;
private double ... ;

public Person(Context context, String person) {
    this.context = context;
    this.person = person;

    loadInformation();
}

private void loadInformation() {
    InputStreamReader inputStreamReader;
    try {
        inputStreamReader = new InputStreamReader(context.getAssets().open("PersonsList.csv"));
        Scanner inputStream = new Scanner(inputStreamReader);
        inputStream.nextLine(); // Ignores the first line
        while (inputStream.hasNext()) {
            String data = inputStream.nextLine(); // Gets a whole line
            String[] line = data.split(","); // Splits the line up into a string array

            if (line.length > 1) {
                if (line[1].equals(person)) {
                    idNumber = Integer.parseInt(line[0]);
                    person = line[1];
                    group = line[2];

                    someAttribute = line[3];

                    scoreOne = Integer.parseInt(line[4]);
                    scoreTwo = Integer.parseInt(line[5]);
                    scoreThree = Integer.parseInt(line[6]);
                    scoreFour= Integer.parseInt(line[7]);
                    scoreFive = Integer.parseInt(line[8]);
                    scoreSix = Integer.parseInt(line[9]);
                    scoreTotal = scoreOne + scoreTwo + scoreThree + scoreFour + scoreFive + scoreSix;

                    // Same code pattern for defining about 10 more attributes
                }
            }
        }
        inputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public int getID() {
    return idNumber;
}

public String getIDAsString() {
    return format(idNumber);
}

private String format(int number) {
    String str_num = String.valueOf(number);
    switch (str_num.length()) {
        case 1:
            str_num = "00" + str_num;
            break;
        case 2:
            str_num = "0" + str_num;
            break;
        case 3:
            // Leave it how it is;
            break;
    }
    return str_num;
}

public String getName() {
    return person;
}

public String getGroup() {
    return group;
}

public String getSomeAttribute() {
    return someAttribute;
}

public int getScoreOne() {
    return scoreOne;
}

public int getScoreTwo() {
    return scoreTwo;
}

...

将你的数组和 ArrayAdapter 基于 Person 而不是 String 并在 之前列出 Persons 设置适配器。这样你只 运行 Person 构造函数一次,而不是每次显示它的视图时。

ArrayList<Person> arr_person = new ArrayList<>();  // Global variable

... 

String data = inputStream.nextLine();
String[] line = data.split(",");
if (line.length > 1) {
    Person person = new Person(context, line[1]);
    arr_person.add(person); 
} 

... 

CustomArrayAdapter adapter = new CustomArrayAdapter(getActivity(), arr_person); 
lv_main.setAdapter(adapter);

... 

package com.mycompany.myapp;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.util.ArrayList;

public class CustomArrayAdapter extends ArrayAdapter<Person> {

    private static class ViewHolder {
        TextView tv_Id;
        TextView tv_Name;
        TextView tv_Group;
    }

    private Context context;
    private ArrayList<Person> persons;

    public CustomArrayAdapter(Context context, ArrayList<Person> persons) {
        super(context, R.layout.listview_advanced, arr_items);
        this.context = context;
        this.persons = persons;
    }

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

        // Get the data item for this position
        Person person = persons.get(position);

        // Check if an existing view is being reused, otherwise inflate the view
        ViewHolder viewHolder; // View lookup cache stored in tag
        if (convertView == null) {
            viewHolder = new ViewHolder();
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.listview_advanced, parent, false);
            viewHolder.tv_Id = (TextView) convertView.findViewById(R.id.lvAdv_text1);
            viewHolder.tv_Name = (TextView) convertView.findViewById(R.id.lvAdv_text2);
            viewHolder.tv_Group = (TextView) convertView.findViewById(R.id.lvAdv_text3);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        // Populate the data into the template view using the data object
        viewHolder.tv_Id.setText(person.getIDAsString());
        viewHolder.tv_Name.setText(person.getName());
        if (person.getGroup().equals("")) {
            viewHolder.tv_Group.setText("");
        } else {
            viewHolder.tv_Group.setText("(" + person.getGroup() + ")");
        }

        // Return the completed view to render on screen
        return convertView;
    }
}