Форум программистов, компьютерный форум CyberForum.ru

Программирование Android

Войти
Регистрация
Восстановить пароль
 
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,727
#1

Как подзаморозить интерфейс? - Программирование Android

29.01.2015, 11:27. Просмотров 354. Ответов 8
Метки нет (Все метки)

Здравствуйте!
Пытаюсь загрузить список ListView из базы. В списке примерно 20 строк. Если делаю это в UI-потоке, то всё грузится меньше секунды, плавно отображается, всё хорошо.
Если делаю в фоновом потоке, открывается примерно с такой же скоростью, но при этом контролы "моргают", список как-то дёргается, сначала исчезает, потом вновь появляется.
Как можно на период работы AsyncTask "заморозить" интерфейс, чтобы он не дёргался?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.01.2015, 11:27
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Как подзаморозить интерфейс? (Программирование Android):

Как удаленно влиять на интерфейс пользователя? - Программирование Android
Как в качестве разработчика спроектировать интерфейс приложения так, чтобы разом у всех пользователей удаленно можно было поменять фон...

[Swipe, Fragment] - интерфейс как у маркета - Программирование Android
Приветствую, которую неделю туплю и не могу сделать интерфейс как у маркета. Задача, сделать интерфейс, чтобы жестом пальца можно было...

Дизайн: как задать программно интерфейс приложения? - Программирование Android
Здравствуйте. Расскажите мне пожалуйста как можно больше про дизайн приложений. Раньше я работал с css html и т.п. Мне...

Iptables, правила, перенаправляющие на интерфейс eth1 все пакеты, приходящие на интерфейс eth0 - Ubuntu Linux
Добрый день, подскажите, пожалуйста, как Iptables написать правила, перенаправляющие на интерфейс eth1 все пакеты, приходящие на интерфейс...

Как сделать интерфейс приложения, написанный в VB6, как в WinXP? - Visual Basic
Как сделать интерфейс приложения, написанный в VB6, как в WinXP?

Подскажите, как в туннельном интерфейсе сконфигурировать начало туннеля, как петлевой интерфейс? - Cisco
Есть неполный пример конфигурации одного из маршрутизаторов. Туннель служить для взаимодействия ipv4 и ipv6. Есть два маршрутизатора(R1 и...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Gabberr
102 / 102 / 17
Регистрация: 13.10.2009
Сообщений: 403
29.01.2015, 11:46 #2
А что в асинтаске происходит?
По идее, если в бекграунде создаётся массив записей из базы, далее массив передаётся в онпост, а там сетится адаптеру, моргать ничего не должно.
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,727
29.01.2015, 14:27  [ТС] #3
Gabberr, примерно такой код. Для того чтобы при обновлении списка старые данные не затирались новыми, пока он ещё не загрузился (с вылетом Exception), создаю второй массив, а затем копирую один из другого.
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    private ArrayList<Rubric> arrList;
 
    task = new LoadList().execute();
 
    private class LoadList extends AsyncTask<Void, Void, Void> {
        private DatabaseHelper dbHelper;
 
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
 
             dbHelper = new DatabaseHelper(context);
        }
 
        @Override
        protected Void doInBackground(Void... params) {
            ArrayList<Rubric> arrList2;
 
            try {
                Cursor cursor = dbHelper.getCursor("запрос");
                if (cursor != null) {
                    if (cursor.moveToFirst()) {
                        arrList2 = new ArrayList<Rubric>();
                        do {
                            arrList2.add(new Rubric(cursor));
                        } while (cursor.moveToNext());
                    } else
                        arrList2 = null;
                    cursor.close();
                } else
                    arrList2 = null;
            } finally {
                dbHelper.close();
            }
 
            if (!isCancelled()) {
                if (arrList != null)
                    arrList.clear();
                arrList = arrList2;
            }
 
            return null;
        }
 
        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
 
            if (!isCancelled()) {
                ArrayAdapter<Rubric> adapter = new ArrayAdapter<Rubric>(
                        context, R.layout.listitem, R.id.text1, arrList);
                lvMain.setAdapter(adapter);
            }
        }
    }
Gabberr
102 / 102 / 17
Регистрация: 13.10.2009
Сообщений: 403
29.01.2015, 14:40 #4
Ну так моргание из-за того что создаётся новый адаптер и сетится списку.
Создай глобальный адаптер и в онпост просто вызывай у него clear() и addAll()
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,727
29.01.2015, 17:57  [ТС] #5
Gabberr, что-то я никак не могу сделать. Всяко попробовал, но всегда при обновлении получаю пустой список.
Вот, например, из http://androiddocs.ru/listview-array...atasetchanged/ взял способ и доработал.
В onPostExecute:
Java
1
2
3
4
5
6
7
8
9
10
                    if (adapter == null) {
                        adapter = new ArrayAdapter<Rubric>(
                                context, R.layout.listitem, R.id.text1, arrList);
                        adapter.setNotifyOnChange(true); // добавил этот метод.
                        lvMain.setAdapter(adapter);
                    } else {
                        adapter.clear();
                        adapter.addAll(arrList);
                        adapter.notifyDataSetChanged();
                    }
При заполнении arrList тоже пробовал всякими способами, всё равно пустой список.
Проверил длины arrList и adapter, получилось 25 элементов что до обновления, что после.
Gabberr
102 / 102 / 17
Регистрация: 13.10.2009
Сообщений: 403
29.01.2015, 18:38 #6
Думаю дело в том, что в онпост у тебя arrList равен нулу.
Не надо в бекграунде делать так
Java
1
2
   arrList.clear();
  arrList = arrList2;
Тут просто перекидывание ссылок получается, возможно, что после отработки этого метода локальный экземпляр arrList2 обнуляется
Передай arrList2 в онпост
Java
1
2
3
4
5
6
7
8
9
  @Override
        protected void onPostExecute(ArrayList<Rubric> array) {
            super.onPostExecute(result);
            if(adapter!=null && array!=null && array.size() > 0){
                adapter.clear();
                adapter.addAll(array);
                adapter.notifyDataSetChanged();
            }
        }
Добавлено через 5 минут
или вот так тогда, но первый вариант правильнее
Java
1
2
   arrList.clear();
  arrList.addAll(arrList2);
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,727
30.01.2015, 10:18  [ТС] #7
Gabberr, в общем, спасибо за советы.
Я и вчера, и сегодня пробовал работать то с arrList, то с arrList2, копировал их по-всякому. Тоже думал на ссылки и очистку массивов. Попробовал переделать AsyncTask. Измерял количество элементов в массивах и адаптере до и после. Оказалось, после выполнения adapter.notifyDataSetChanged() длина адаптера равнялась 0. Но это бы и ладно, можно копаться дальше, но я вот чего заметил.
У меня-то задача немного другая была. Я заходил в некий фрагмент, грузил список. Если он грузился в UI-потоке, всё было гладко, если в фоновом - моргало. Дальше переходил в другой фрагмент, потом возвращался в первый. И снова моргало. Т.е. установка setAdapter происходит каждый раз, и мне не требуется обновлять список. Проблема именно в этом - как перед установкой setAdapter заморозить интерфейс?

Добавлено через 5 минут
Иногда бывает такая ситуация, когда список не успевает быстро загрузиться, например, если пользователь быстро переходит по фрагментам туда-сюда. Тогда, в принципе, может возникнуть исключительная ситуация с сообщением, что другие данные грузятся в тот же адаптер. Поэтому я пытался добавить массив arrList2, но не уверен, что это правильно.
Gabberr
102 / 102 / 17
Регистрация: 13.10.2009
Сообщений: 403
30.01.2015, 10:19 #8
Проект сильно секретный?)
я б посмотрел, поковырял
CoolMind
418 / 401 / 65
Регистрация: 06.10.2012
Сообщений: 1,727
30.01.2015, 12:01  [ТС] #9
Gabberr, да, к сожалению, пишем для организации. Но за помощь спасибо. Будут идеи - напишу.

Добавлено через 1 час 34 минуты
Немного неправильно сформулировал и заодно повторно для себя уяснил.
Если загружать данные в фоновом потоке, то мелькание будет, потому что сначала покажется чистый фрагмент, потом секунду будут грузиться данные, затем они добавятся в список.
Если данные загружать в основном потоке, то мелькания не будет, потому что фрагмент не отображается, пока не загрузятся все данные. Т.е. будет рисоваться старый фрагмент, а спустя секунду откроется новый с уже загруженными данными. Но при этом, конечно же, нельзя отобразить прогресс (впрочем, он нужен для операций дольше секунды).
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.01.2015, 12:01
Привет! Вот еще темы с ответами:

База данных "учебный план специальности". GUI. Графический интерфейс. Пользовательский интерфейс - Prolog
Всем привет. Свалилась на меня, значит, курсовая по прологу. Все бы ничего, да реализовать ее надо через графический интерфейс. На турбо...

Узнать имя компонента, реализующего интерфейс и имя категории, в которую этот интерфейс входит - C++ COM
Темы очень близки. Поэтому два в одном решил сделать. Вот я взял у Роджерсона код: HRESULT hr =...

Как настроить интерфейс - Windows Phone
Как настроить интерфейс

Как исправить интерфейс - C++ Builder
изучал vb.net. Решил изучать Borland C++ Builder. Скачал 6 версию. Запустил, и увидел что контроллы ужасно не красивые(практически все)....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
30.01.2015, 12:01
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru