На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Hsilgos
  
> Autocomplete для EditText
    Всем привет!

    Еще один вопрос по Android, для которого решил все же создать отдельную тему. Пишу приложение для заказа такси нашей фирмы. Уже есть форма для создания заказа, в том числе и адресные поля (улица, номер дома, корпус) для точки отправления и точки назначения. Форма уже в первом приближении работает, даже работает расчет заказа и отправление его на сервер, в реальной таксишной программе эти заказы появляются.

    Но есть необходимость сделать autocomplete для поля с названием улицы (или объекта, например, станции метро). То есть, пользователь вводит несколько букв из названия, а ему предлагается список из названий, в которых эта последовательность есть, он сможет выбрать подходящее без необходимости вводить полностью весь текст с клавиатуры. На форме заказа на сайте это реализовано с помощью JQuery UI Autocomplete, если кто в теме, во время тестов и я, и шеф всегда это используем (чтобы адреса бац-бац:). В свое время пришлось немного повозиться, это было сделано предыдущим программистом, но мне надо было портануться на более свежую версию библиотеки, да что-то там еще обновил, вроде что-то не то с кодировкой было.

    Соответственно, у меня вопросы. Как сделать такое для Android? Может быть, есть смысл найти готовый бесплатный компонент? Или стоит все же сделать самому? Как хранить список названий в apk удобным образом (провожу тут аналогию с ресурсами в приложениях Windows, в свое время делал игру в города с компьютером, так в кастомном ресурсе держал названия городов России, из которых компьютер подбирал свои ответы на ходы игрока).
      Есть уже готовый компонент AutoCompleteTextView
      http://developer.android.com/resources/tut...tocomplete.html
      http://developer.android.com/reference/and...teTextView.html

      Массивы можно хранить в ресурсах: http://developer.android.com/guide/topics/...-resources.html

      ЗЫ: вообще рекомендую перед тем как приступить к Андроиду хотя бы в общих чертах ознакомиться с документацией на http://developer.android.com/guide/index.html
        Цитата [S]mike @
        Ы: вообще рекомендую перед тем как приступить к Андроиду хотя бы в общих чертах ознакомиться с документацией на http://developer.android.com/guide/index.html


        Я документацией пользуюсь, в том числе и в гайд приходилось заглядывать. Просто что-то осбо некогда сесть и изучит все от корки до корки. Один раз пытался это сделать, какие-то начальные сведения получил, достаточные для программирования простых приложений. Сейчас же, если что надо, то осваиваю по ходу дела.

        Про то, что есть стандартный Autocomplete не знал, спасибо!
          Цитата Homez @
          Просто что-то осбо некогда сесть и изучит все от корки до корки.

          Очень и очень зря! Просто Вы пытаетесь мыслить категориями десктопных приложений, не имея понятия, какой инструментарий предоставляет Вам Андроид. В результате просто загоняете себя в тупик. Так что рекомендую все-таки выделить время на изучение. В гугловой документации написано все достаточно кратко и емко.
            Думаю тут о покупке бумажной книги. Какую посоветуете? Я живу и работаю в Питере, если это имеет значение:)
              Я в соседней теме эту книгу рекомендовал http://www.ozon.ru/context/detail/id/6752687/ Автор - Android developer advocate в Гугле.

              Очень доступно, на примерах показывается, как программировать под Андроид. Читать рекомендую конечно же на языке оригинала, написано не особо сложным языком.
                Да, спасибо!
                  Автокомплит заюзал, вроде все нормально. На эмуляторе работает отстойно долго, но на то он и эмулятор. Шеф пробовал на смартфоне своем, говорит, что все ок.

                  Но пришлось обойти одну досадную фишку. Пытался эти строки (около 5000) засунуть в xml-массив в ресурсе. Когда программно этот массив читал, не прокатывало ни в эмуляторе, ни на телефоне. LogCat выдавал ReferenceTable overflow (max = 512). Это у всех так? На StackOverflow или где-то еще вычитал, что баг в ядре андроида, и использовал подсказанное там же решение использовать в качестве источника строк "сырой" ресурс. Кто нибудь прокомментирует?
                    Возможно, у всего есть свои ограничения :) Но и решения есть. Можно сохранить в XML файл и поместить в папку asset - таким образом данные будут всегда вместе с программой и доступны через функции Андроида.
                      Цитата [S]mike @
                      Возможно, у всего есть свои ограничения

                      Там точно баг. У челов валилось и при 1000 строк, это же может быть очень мало. А то, что это баг, кто-то писал, вроде он видел нативные сорцы на C++, там память не оcвобожадется банально:) Может, на более новых версиях это решили.

                      Цитата [S]mike @
                      Можно сохранить в XML файл и поместить в папку asset - таким образом данные будут всегда вместе с программой и доступны через функции Андроида.


                      xml в итоге занимает больше. без его компрессии у меня программа весила за 300 кило. Когда же я в итоге использовал обычный файл из строк, разделенных переводос строки, причес в кодировке Windows-1251, у меня программа стала весить немногим более 50 кило:) Файл этот я создал как ресурс raw и уже не вижу необходимости возврата к xml, и так все работает.
                        Цитата Homez @
                        Там точно баг. У челов валилось и при 1000 строк, это же может быть очень мало. А то, что это баг, кто-то писал, вроде он видел нативные сорцы на C++, там память не оcвобожадется банально:) Может, на более новых версиях это решили.

                        С другой стороны, ресурсы - это не база данных. Так что там нельзя хранить большие количества данные. Тем более что простой текстовый файл (не XML) занимает гораздо меньше места ;)
                          я не считаю, что 5000 строк - это большой объем. Да даже и 1000 - это уже не работало.

                          Добавлено
                          Цитата [S]mike @
                          Тем более что простой текстовый файл (не XML) занимает гораздо меньше места ;)


                          Так файл и так у меня включен как ресурс.
                            Воскрешаю эту тему. Итак, я заюзал AutocompleteTextView, а массив строк, который я подсовываю его ArrayAdapter хранится у меня в raw-ресурсе. Но там сыше 5000 строк, в результате у меня и на эмуляторе, и на простеньком устройстве Huawei U8180 все это работает очень медленно. В моих тестах я практически никогда не дожидаюсь выпадения подходящих вариантов и ввожу названия улиц целиком с клавиатуры. Например, набирая Автовская и доходя до буквы С, я только-только получаю список для Ав, чтобы дождаться более подходящего списка, приходится еще ждать несколько секунд. У шефа на его одном из флагманов HTC это работает намного быстрее. Но мне не хочется здесь иметь дискриминацию для маломощных устройств, в конце концов, было бы приятно и у себя получать результат быстро. Поэтому вопрос: можно ли как-то убыстрить формирование списка подходящих строк для AutocompleteTextView? Быстрым решением было бы разделить весь этот массив с названиями улиц на несколько массивов в зависимости от значения первой буквы/символа и в каждом конкретном случае адресовать уже более куда маленький массив. Но шеф желает, чтобы совпадения могли быть не только от начала слова, но и потом. Была у кого-нибудь подобная задача?
                              Хранить строки sqlite таблице, и выборку делать через подходящий SQL оператор.

                              Добавлено
                              Цитата Homez @
                              Но шеф желает, чтобы совпадения могли быть не только от начала слова, но и потом. Была у кого-нибудь подобная задача?

                              тут LIKE в помощь.
                                А как мне такую базу создать? Нужно каждый раз ее делать при запуске приложения, или есть возможность один раз ее забацать, а потом использовать только для чтения?
                                  Конечно есть возможность один раз создать и много раз использовать http://www.vogella.com/articles/AndroidSQLite/article.html
                                    Ну уже похоже не в этом необходимости. В доступной мне базе названий улиц и прочих городских объектов все равно все строки в верхнем регистре. Поэтому я просто написал свой TextWatcher, в котором для каждой строки из массива вызывается метод contains() с приведенным к верхнему регистру пользовательским вводом. У меня это очень хорошо стало работать, почти без тормозов (пробовал на телефоне). А у шефа все как и было, но у него телефон мощный. ЕдинственноеЮ что осталось - это в отдельном потоке это все запускать, чтобы не замедлять сам ввод в поле.
                                      Homez, по собственному опыту тоже сталкивался с тем, что долго тупило при работе с базой и AutoCompleteTextView. В итоге выяснилось, что тормозит именно это заполнение AutoCompleteTextView. В итоге сделал ограничение на 50 записей - всё равно целое полотенце пользователю будет листать неудобно, а если не будет нужного результата, так можно и ещё одну буковку дописать. В итоге всё летает и на эмуляторе, и на довольно слабых девайсах (Motorola Droid, HTC Wildfire).
                                        Хрен, да тут дело в другом было. Все равно эти 50 записей нужно как-то выбрать из имеющегося обширного массива - 5190 строк, все равно ведь нужно все просматривать. у меня тормозило и при 4ых подходящих вариантах.

                                        Ну допустим, когда подходит слишком много вариантов, действительно, можно при достижении некоторого порогового количества поиск прекращать. Но а когда подходит из всего массива только четыре - тут уже приходится дочитать до конца. Ну хотя, можно придумать всякие хитрые алгоритмы, например, начальник (он не программист, но порой подсказывает просто гениальные вещи) надумал, что можно при наборе каждой следующей буквы выбирать совпадения только из тех строк, которые подошли на предыдущем шаге. Но тут скорость выборки тогла получится с разбросом - чем меньше букв, тем она будет меньше. Правда, можно показывать варианты, например, начиная с 4ых букв, а пока пользователь их набирает, постепенно сужать массив, в котором поиск будет вестись, просто не выводя эти промежуточные варианты пользователю.

                                        Но я сейчас вполне доволен скоростью. Подозреваю, что мое устройство одно из самых слабеньких (второе по дешивизне на Яндекс.Маркет для Питера среди Android-смартфонов. А доводить до полного блеска, чтобы летало и на эмуляторе, не вижу смысла, лучше потрачу это время на что-нибудь другое. Однако, на эмуляторе так и не пробовал, попробую завтра.

                                        Думаю, что внутренняя реализация AutoСomleteTextView не особо удачная и не была задумана для работы с такими большими массивами строк, как список улиц в городе масштаба Санкт-Петербурга. Я для начала пробовал формировать массив для ArrayAdapter с помощью отбора на основе регулярных выражений. И то намного быстрее стало работать. Сколько же лишнего кода там выполняется для подбора вариантов из массива в распоряжении?
                                          Цитата Homez @
                                          все равно ведь нужно все просматривать.

                                          А LIMIT 50 при запросе к базе отменили? ;)
                                            Ага, и он непременно будет работать, когда в базе 10 000 строк, а критерию удовлетворяют только 2-3:) При этом гарантированно выборка будет идти только по сотне-другой строк:)
                                              Цитата Homez @
                                              Ага, и он непременно будет работать, когда в базе 10 000 строк, а критерию удовлетворяют только 2-3:) При этом гарантированно выборка будет идти только по сотне-другой строк

                                              Причём тут это? Если загвоздка в большой базе, то индексация спасёт отца русской демократии =)
                                                Ну так а как тут проиндексировать, когда набранные 3 буквы могут быть в какой угодно строке, если говорить о базе названий улиц большого города, причем интересуют совпадения не только с начала строки названия, но и в любом ее месте?
                                                  Цитата Homez @
                                                  Ну так а как тут проиндексировать, когда набранные 3 буквы могут быть в какой угодно строке, если говорить о базе названий улиц большого города, причем интересуют совпадения не только с начала строки названия, но и в любом ее месте?

                                                  Для этого есть полнотекстовые индексы, SQLite их поддерживает.
                                                  1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                                  0 пользователей:


                                                  Рейтинг@Mail.ru
                                                  [ Script execution time: 0,0503 ]   [ 14 queries used ]   [ Generated: 9.07.25, 07:55 GMT ]