Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/220.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
填充AutoCompleteTextView时出现Android性能问题_Android_Performance_Autocompletetextview_Cyanogenmod - Fatal编程技术网

填充AutoCompleteTextView时出现Android性能问题

填充AutoCompleteTextView时出现Android性能问题,android,performance,autocompletetextview,cyanogenmod,Android,Performance,Autocompletetextview,Cyanogenmod,我有一个动态填充的AutoCompleteTextView。我动态地这样做,因为我有大约10000个提案(街道)要展示,所以我根据它们的第一个字母来划分列表。假设有人输入“a”,我用以“a”开头的所有街道填充适配器。这在emulator中运行得很快,在我的旧手机Android 2.1上运行得也很快。突然,我意识到清单的填写非常缓慢。填充大约需要10秒。但我认为这不是我的代码问题,而是我的手机问题。不久前,我用CyanogenMod 7.2.0-blade升级到Android 2.3.7。我绝对肯

我有一个动态填充的AutoCompleteTextView。我动态地这样做,因为我有大约10000个提案(街道)要展示,所以我根据它们的第一个字母来划分列表。假设有人输入“a”,我用以“a”开头的所有街道填充适配器。这在emulator中运行得很快,在我的旧手机Android 2.1上运行得也很快。突然,我意识到清单的填写非常缓慢。填充大约需要10秒。但我认为这不是我的代码问题,而是我的手机问题。不久前,我用CyanogenMod 7.2.0-blade升级到Android 2.3.7。我绝对肯定我以前从来没有遇到过这个问题,因为我永远不会在生产中投入一些滞后的实现。我在跟踪时认出了一些奇怪的东西。所有性能都浪费在名为
TextUtils.hasArabicCharacters()的方法上。请看青色条

我找不到关于这个方法的任何东西。TextUtils没有hasarabiccharacter,所以我猜它是一些专有的东西->CyanogenMod如果我在任何模拟器上跟踪相同的代码,则不会调用名为'hasArabicCharacters'的方法,并且自动完成行为非常快。在Android 2.1、2.3.3和4.1.2模拟器下测试

这是调用链(向上):

TextUtils.hasArabicCharacter()->TextUtils.reformearabic()-> Paint.measureText()->Styled.drawDirectionalRun()-> Styled.measureText()->BoringLayout.isBoring()-> TextView.onMeasure()->View.measure()->ListView.measureScrapChild() ->ListView.MeasureHeightoChildren()->AutoCompleteTextView.buildDropdown()-> AutoCompleteTextView.showDropDown()-> AutoCompleteTextView.updateDropDownForFilter()-> AutoCompleteTextView.access$1700-> AutoCompleteTextView$PopulateDataSetObserver$1.run()-> Handler.handleCallback()->Handler.dispatchMessage()

这就是我填充适配器的方式。也许我可以申请一些变通办法。有什么想法吗

活动:

        final StreetArrayAdapter adapter = new StreetArrayAdapter(this, R.layout.simple_dropdown_item_1line);

        autoCompleteTextView.setAdapter(adapter);
        autoCompleteTextView.setValidator(new Validator());
        autoCompleteTextView.setThreshold(0);
        autoCompleteTextView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                streetInfoField.setText("");
            }
        });

        autoCompleteTextView.addTextChangedListener(new StreetTextWatcher(adapter));

......

    class Validator implements AutoCompleteTextView.Validator {

        @Override
        public CharSequence fixText(CharSequence invalidText) {
            return "";
        }

        @Override
        public boolean isValid(CharSequence text) {
            Log.v(TAG, "Checking if valid: " + text);
            String[] streets = StreetNameFactory.getStreetsWithLetter(text.subSequence(0, 1).toString().toUpperCase(Locale.US));

            Arrays.sort(streets);
            if (Arrays.binarySearch(streets, text.toString()) >= 0) {
                return true;
            }

            return false;
        }
    }
public class StreetTextWatcher implements TextWatcher {

    private final StreetArrayAdapter adapter;
    private boolean alreadyAdded = false;

    public StreetTextWatcher(StreetArrayAdapter adapter) {
        this.adapter = adapter;
    }

    @Override
    public void afterTextChanged(Editable s) {
        //not used
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        if (s.length() < 1)  {
            adapter.clear();

            alreadyAdded = false;
        }
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {           
        if (s.length() == 1) {
            populateAdapter(s);

            alreadyAdded = true;
        }
    }

    private synchronized void populateAdapter(CharSequence s) { 
        String charSequence = s.toString().toUpperCase(Locale.US);
        if (charSequence.startsWith("A") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_A);
        }

        if (charSequence.startsWith("Ä") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_A);
        }

        if (charSequence.startsWith("B") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_B);
        }

        if (charSequence.startsWith("C") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_C);
        }

        if (charSequence.startsWith("D") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_D);
        }

        if (charSequence.startsWith("E") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_E);
        }
        //more code....

        if (charSequence.startsWith("Z") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_Z);
        }
        if (Pattern.matches("[1-9]", s.toString()) && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_NUMBERS);
        }
    }
}
public class StreetArrayAdapter extends ArrayAdapter<String> {

    private final String TAG = StreetArrayAdapter.class.getSimpleName();

    public StreetArrayAdapter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);
    }

    public void addAll(String[] streets) {
        Log.i(TAG, "BEGIN LIST FILL at: " + new Date(System.currentTimeMillis()).toString());
        for (String street : streets) {
            add(street);
        }
        Log.i(TAG, "END LIST FILL at: " + new Date(System.currentTimeMillis()).toString());
    }
}
StreetTextWatcher:

        final StreetArrayAdapter adapter = new StreetArrayAdapter(this, R.layout.simple_dropdown_item_1line);

        autoCompleteTextView.setAdapter(adapter);
        autoCompleteTextView.setValidator(new Validator());
        autoCompleteTextView.setThreshold(0);
        autoCompleteTextView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                streetInfoField.setText("");
            }
        });

        autoCompleteTextView.addTextChangedListener(new StreetTextWatcher(adapter));

......

    class Validator implements AutoCompleteTextView.Validator {

        @Override
        public CharSequence fixText(CharSequence invalidText) {
            return "";
        }

        @Override
        public boolean isValid(CharSequence text) {
            Log.v(TAG, "Checking if valid: " + text);
            String[] streets = StreetNameFactory.getStreetsWithLetter(text.subSequence(0, 1).toString().toUpperCase(Locale.US));

            Arrays.sort(streets);
            if (Arrays.binarySearch(streets, text.toString()) >= 0) {
                return true;
            }

            return false;
        }
    }
public class StreetTextWatcher implements TextWatcher {

    private final StreetArrayAdapter adapter;
    private boolean alreadyAdded = false;

    public StreetTextWatcher(StreetArrayAdapter adapter) {
        this.adapter = adapter;
    }

    @Override
    public void afterTextChanged(Editable s) {
        //not used
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        if (s.length() < 1)  {
            adapter.clear();

            alreadyAdded = false;
        }
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {           
        if (s.length() == 1) {
            populateAdapter(s);

            alreadyAdded = true;
        }
    }

    private synchronized void populateAdapter(CharSequence s) { 
        String charSequence = s.toString().toUpperCase(Locale.US);
        if (charSequence.startsWith("A") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_A);
        }

        if (charSequence.startsWith("Ä") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_A);
        }

        if (charSequence.startsWith("B") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_B);
        }

        if (charSequence.startsWith("C") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_C);
        }

        if (charSequence.startsWith("D") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_D);
        }

        if (charSequence.startsWith("E") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_E);
        }
        //more code....

        if (charSequence.startsWith("Z") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_Z);
        }
        if (Pattern.matches("[1-9]", s.toString()) && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_NUMBERS);
        }
    }
}
public class StreetArrayAdapter extends ArrayAdapter<String> {

    private final String TAG = StreetArrayAdapter.class.getSimpleName();

    public StreetArrayAdapter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);
    }

    public void addAll(String[] streets) {
        Log.i(TAG, "BEGIN LIST FILL at: " + new Date(System.currentTimeMillis()).toString());
        for (String street : streets) {
            add(street);
        }
        Log.i(TAG, "END LIST FILL at: " + new Date(System.currentTimeMillis()).toString());
    }
}
公共类StreetTextWatcher实现TextWatcher{
专用最终街道适配器;
私有布尔值alreadyAdded=false;
公共StreetExtWatcher(StreetArray适配器){
this.adapter=适配器;
}
@凌驾
公共无效后文本已更改(可编辑){
//不用
}
@凌驾
更改前文本之前的公共void(字符序列s、int start、int count、int after){
如果(s.长度()<1){
适配器。清除();
alreadyAdded=假;
}
}
@凌驾
public void onTextChanged(字符序列,int start,int before,int count){
如果(s.长度()==1){
民众适应者;
alreadyAdded=true;
}
}
私有同步的void populateAdapter(字符序列){
String charSequence=s.toString().toUpperCase(Locale.US);
if(charSequence.startsWith(“A”)&&!已添加){
adapter.addAll(StreetNames.STREETS_A);
}
if(已添加的字符序列开始){
adapter.addAll(StreetNames.STREETS_A);
}
if(charSequence.startsWith(“B”)&&!已添加){
adapter.addAll(StreetNames.STREETS_B);
}
if(charSequence.startsWith(“C”)和&!alreadyAdded){
adapter.addAll(StreetNames.STREETS_C);
}
if(charSequence.startsWith(“D”)和&!alreadyAdded){
adapter.addAll(StreetNames.STREETS\u D);
}
if(charSequence.startsWith(“E”)&&!已添加){
adapter.addAll(StreetNames.STREETS_E);
}
//更多代码。。。。
if(charSequence.startsWith(“Z”)&&!已添加){
adapter.addAll(StreetNames.streetsz);
}
if(Pattern.matches(“[1-9]”),s.toString())&&&!alreadyAdded){
adapter.addAll(街道名称、街道编号);
}
}
}
StreetArray适配器:

        final StreetArrayAdapter adapter = new StreetArrayAdapter(this, R.layout.simple_dropdown_item_1line);

        autoCompleteTextView.setAdapter(adapter);
        autoCompleteTextView.setValidator(new Validator());
        autoCompleteTextView.setThreshold(0);
        autoCompleteTextView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                streetInfoField.setText("");
            }
        });

        autoCompleteTextView.addTextChangedListener(new StreetTextWatcher(adapter));

......

    class Validator implements AutoCompleteTextView.Validator {

        @Override
        public CharSequence fixText(CharSequence invalidText) {
            return "";
        }

        @Override
        public boolean isValid(CharSequence text) {
            Log.v(TAG, "Checking if valid: " + text);
            String[] streets = StreetNameFactory.getStreetsWithLetter(text.subSequence(0, 1).toString().toUpperCase(Locale.US));

            Arrays.sort(streets);
            if (Arrays.binarySearch(streets, text.toString()) >= 0) {
                return true;
            }

            return false;
        }
    }
public class StreetTextWatcher implements TextWatcher {

    private final StreetArrayAdapter adapter;
    private boolean alreadyAdded = false;

    public StreetTextWatcher(StreetArrayAdapter adapter) {
        this.adapter = adapter;
    }

    @Override
    public void afterTextChanged(Editable s) {
        //not used
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        if (s.length() < 1)  {
            adapter.clear();

            alreadyAdded = false;
        }
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {           
        if (s.length() == 1) {
            populateAdapter(s);

            alreadyAdded = true;
        }
    }

    private synchronized void populateAdapter(CharSequence s) { 
        String charSequence = s.toString().toUpperCase(Locale.US);
        if (charSequence.startsWith("A") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_A);
        }

        if (charSequence.startsWith("Ä") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_A);
        }

        if (charSequence.startsWith("B") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_B);
        }

        if (charSequence.startsWith("C") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_C);
        }

        if (charSequence.startsWith("D") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_D);
        }

        if (charSequence.startsWith("E") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_E);
        }
        //more code....

        if (charSequence.startsWith("Z") && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_Z);
        }
        if (Pattern.matches("[1-9]", s.toString()) && !alreadyAdded)  {
            adapter.addAll(StreetNames.STREETS_NUMBERS);
        }
    }
}
public class StreetArrayAdapter extends ArrayAdapter<String> {

    private final String TAG = StreetArrayAdapter.class.getSimpleName();

    public StreetArrayAdapter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);
    }

    public void addAll(String[] streets) {
        Log.i(TAG, "BEGIN LIST FILL at: " + new Date(System.currentTimeMillis()).toString());
        for (String street : streets) {
            add(street);
        }
        Log.i(TAG, "END LIST FILL at: " + new Date(System.currentTimeMillis()).toString());
    }
}
public类streetrayadapter扩展了ArrayAdapter{
private final String TAG=streetarayadapter.class.getSimpleName();
公共StreetArray适配器(上下文,int textViewResourceId){
super(上下文,textViewResourceId);
}
公共void addAll(字符串[]街道){
Log.i(标记,“开始列表填充时间:”+新日期(System.currentTimeMillis()).toString());
适用于(字符串街:街道){
加设(街道);;
}
Log.i(标记,“结束列表填写时间:”+新日期(System.currentTimeMillis()).toString());
}
}
STREETS\u A、STREETS\u B、STREETS\u C只是我分配的字符串数组

[更新]

我找到了一个很好的解决办法。输入第一个字母时,我不能加载列表。当我在输入至少3个字母(StreetTextWatcher.onTextChange)后加载列表时,我没有冻结,而且下拉速度非常快。此外,用户甚至可能不认识到更改

我认为这是CyanogenMod 7.2的一个缺陷

查看源代码可以发现,在每个(在您的例子中)调用中,
都会调用BoringLayout.isBoring()
,这看起来是一个相当繁重的方法(它也调用了很多其他方法)

我认为在代码中解决这个问题可能很困难。我在寻找一些标志,也许你可以设置它来省略这个沉重的“阿拉伯语”方法,比如
setIsArabic(false)
,但我没有找到任何东西。也许您可以像建议的那样替换例如
Styled.measureText()
的字节码,但这似乎相当耗时

在较新的版本中,例如CyanogenMod 10.1,其行为是不同的。因此,也许只要升级您的CyanogenMod,问题就会消失。

TextUtils.hasArabic