Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   www.boolean.name > Программирование игр для мобильных телефонов > Android

Android Разработка игр на платформе Android

Ответ
 
Опции темы
Старый 24.12.2015, 07:16   #1
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,342
Написано 473 полезных сообщений
(для 852 пользователей)
Полезные находки

Предлагаю в этой теме собирать всякие полезные находки, которые вы используете.
Решение тех или иных проблем.
Ссылки на что-то интересное.
(Offline)
 
Ответить с цитированием
Старый 24.12.2015, 07:24   #2
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,342
Написано 473 полезных сообщений
(для 852 пользователей)
Ответ: Полезные находки

Недавно делал восстановление открытых окошек после поворота экрана.
Самодельный велосипед с сохранением данных в преференсы.
А тут нашёл простое решение - http://developer.android.com/referen...#configChanges
Прописываем в манифесте для активити строку
android:configChanges="orientation|screenSize|locale|keyboardHidden" 
И теперь при повороте экрана активити не пересоздаётся.
Если нужно обработать изменения (н-р, обновить лэйауты для гориз. ориент.), то добавляем колбэк
@Override
public void onConfigurationChanged(Configuration newConfig) {
    
super.onConfigurationChanged(newConfig);
    
/** обработка конфига ниже **/

Профит - поворот делается почти мгновенно, все вьюхи остаются видимые, включая popupMenu, лоадеры для списков заново не стартуют и т.д.

Если кто-то знает проблемные места этого подхода, расскажите.
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо Жека за это полезное сообщение:
burovalex (02.03.2016), St_AnGer (24.12.2015)
Старый 24.12.2015, 12:28   #3
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,342
Написано 473 полезных сообщений
(для 852 пользователей)
Ответ: Полезные находки

Свойство android:clipToPadding="false"

Позволяет при наличии паддингов у элемента видеть содержимое такого размера, будто паддингов нет.
Может быть полезно в списках - когда нужен отступ сверху / снизу, и чтобы содержимое не выглядело обрезанным.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
burovalex (02.03.2016)
Старый 26.12.2015, 08:24   #4
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,342
Написано 473 полезных сообщений
(для 852 пользователей)
Ответ: Полезные находки

Использование AlertDialog.Builder

1. Использовать android.support.v7.app.AlertDialog - для получения стиля material design, ничего делать не нужно, диалог сразу будет в стиле материал при импорте суппорт-версии.

2. Создание диалога
AlertDialog dialog = builder.create();

a) если после создания назначать кнопки через setXXXButton, то их не будет в диалоге. это очевидно.

б) назначение лисенеров, например,
builder.setOnDismissListener
после создания диалога - лисенер не применится. тоже очевидно, но можно не доглядеть. как?
например, какая-то вьюха внутри диалога должна по нажатию закрывать диалог. значит, нам нужно создать диалог раньше, чем это вьюшку. и значит, лисенеры нужно навесить ещё раньше. есть вероятность несоблюдения этого порядка.

в) при нажатии на диалоговские кнопки, диалог закрывается. это не всегда уместно. часто нужна проверка введённых данных.
для этого ставим кнопке listener в null, и далее после создания диалога
Button b dialog.getButton(AlertDialog.BUTTON_POSITIVE);
b.setOnClickListener(new View.OnClickListener() {
    @
Override
    
public void onClick(View v) {
        
/** делаем что-то **/
    
}
}); 
также можно скрывать / показывать эти кнопки как любые другие вьюхи через setVisibility.

г) Назначение dialog.setOnShowListener() после вызова dialog.show() - слушатель не сработает.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
St_AnGer (26.12.2015)
Старый 26.12.2015, 12:16   #5
FireOwl
Бывалый
 
Аватар для FireOwl
 
Регистрация: 16.09.2009
Адрес: Sun system
Сообщений: 831
Написано 442 полезных сообщений
(для 1,836 пользователей)
Ответ: Полезные находки

Сообщение от Жека Посмотреть сообщение
Недавно делал восстановление открытых окошек после поворота экрана.
Самодельный велосипед с сохранением данных в преференсы.
А тут нашёл простое решение - http://developer.android.com/referen...#configChanges
Прописываем в манифесте для активити строку
android:configChanges="orientation|screenSize|locale|keyboardHidden" 
И теперь при повороте экрана активити не пересоздаётся.
Вообще, насколько я знаю, "самопальный велосипед" с сохранением данных (в savedInstance Bundle) это и есть рекомендуемый путь.
Перехватом configChanges надо пользоваться осторожно, т.к. андроид все равно найдет способ уничтожить твой activity и пересоздать его заново.

Например - юзер сворачивает приложение в фон -> чем-то там занят -> Андроид решил что ему не хватает оперативной памяти -> убил твой activity -> юзер закончил свои дела, и вернулся к твоей программе -> Андроид создает activity заново.
__________________
N"Gasta! Kvata! Kvakis!
Ahkstas so novajxletero (oix jhemile) so Ranetauw.
(Offline)
 
Ответить с цитированием
Старый 27.12.2015, 02:26   #6
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,342
Написано 473 полезных сообщений
(для 852 пользователей)
Ответ: Полезные находки

Пересоздание активити после его закрытия/сворачивания - не проблема, создаём всё с чистого листа и всё.
Проблема именно в повороте экрана, когда юзер ожидает, что прога должна оставаться такой, какая была до поворота.
(Offline)
 
Ответить с цитированием
Старый 31.01.2016, 14:02   #7
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,342
Написано 473 полезных сообщений
(для 852 пользователей)
Ответ: Полезные находки

Фильтрация данных на уровне адаптера VS на уровне sql-запроса.

При работе с базой данных иногда нужно отсеять часть информации.

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

Но сегодня пришла идея - отсеивать "нулевые" записи в адаптере, который выводит информацию на экран (CursorAdapter).

Для этого добавляем в адаптер 2 метода:
@Override
public int getViewTypeCount() {
    return 
2;
}

@
Override
public int getItemViewType(int position) {
    if (
isShowZeroBalance)
        return 
TYPE_NORMAL;
    
long balance extractBalanceAt(position); // достаём баланс из курсора
    
return (balance == 0) ? TYPE_EMPTY TYPE_NORMAL;

далее в методе
public View newView(Context contextCursor cursorViewGroup parent
делаем проверку типа, если TYPE_NORMAL, то создаём элемент как и раньше, а иначе создаём пустой лэйаут размером 0х0 dp.
И в методе
public void bindView(View viewContext context, final Cursor cursor
в самом начале делаем проверку
int type getItemViewType(cursor.getPosition());
if (
type == TYPE_EMPTY) {
    return;

Получаем тот же итоговый результат, но без лишнего запроса к базе.
И наш единожды запрошенный курсор хранит информацию обо всех контактах в таблице, можем использовать его для любых нужд.

Последний раз редактировалось Жека, 31.01.2016 в 16:55. Причина: добавил инфу о том, что нужно создавать пустую вьюху для нулевых балансов
(Offline)
 
Ответить с цитированием
Старый 03.06.2016, 07:07   #8
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,342
Написано 473 полезных сообщений
(для 852 пользователей)
Ответ: Полезные находки

меню Analyze | Inspect Code...

В Android Studio есть полезная штука - анализ кода, который подсказывает потенциальные ошибки типа "присваивание переменной в саму себя" (после рефактора можно не заметить) и неиспользуемые методы, полезно для чистки большого проекта от шлака.
(Offline)
 
Ответить с цитированием
Старый 23.01.2017, 09:36   #9
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,342
Написано 473 полезных сообщений
(для 852 пользователей)
Ответ: Полезные находки

Gradle Retrolambda Plugin (ссылка)

Что: Плагин, который позволяет юзать лямбды в старых версиях джавы (нативно они доступны в java 8 ).

Зачем: повышает читабельность кода, избавляет от необходимости писать "лишний" шлак код.

Примеры:

было
view.setOnClickListener(new View.OnClickListener() {
    @
Override
    
public void onClick(View v) {
        
/** делаем что-то **/
    
}
}); 
стало
view.setOnClickListener(-> /** делаем что-то, однострочный блок. **/); 
или
view.setOnClickListener(-> {
    
/** делаем что-то, многострочный блок. **/
}); 
Ещё частый гость - Runnable с единственным методом run.

слушатель для кнопки "оставить отзыв".
было
View.OnClickListener listener = new View.OnClickListener() {
    @
Override
    
public void onClick(View v) {
        
startActivity(new Intent(Intent.ACTION_VIEWUri.parse("market://details?id=" getPackageName())));
        
Metrica.reportEvent("rate us dialog : rate");
        
rateHelper.setState(RateHelper.STATE_RATED);
        
dialog.dismiss();

        
/** показываем диалог "спасибо за отзыв" через 1,2 сек */
        
handler.postDelayed(new Runnable() {
            @
Override
            
public void run() {
                
showDialog_RateUsRated();
            }
        }, 
1200);
    }
}; 
стало
View.OnClickListener listener -> { // упрощение #1
    
    
startActivity(new Intent(Intent.ACTION_VIEWUri.parse("market://details?id=" getPackageName())));
    
Metrica.reportEvent("rate us dialog : rate");
    
rateHelper.setState(RateHelper.STATE_RATED);
    
dialog.dismiss();

    
/** показываем диалог "спасибо за отзыв" через 1,2 сек */
    
handler.postDelayed(() -> showDialog_RateUsRated(), 1200); // упрощение #2
}; 
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
St_AnGer (23.01.2017)
Старый 13.02.2017, 05:31   #10
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,342
Написано 473 полезных сообщений
(для 852 пользователей)
Ответ: Полезные находки

Массивы в шаблонных типах в Java.

Интро. Я глядя на RxJava решил сделать некое подобие, но попроще.
Полученную штуку назвал CallChain - это цепочки вызовов методов.
Суть: составляем последовательность операций в цепочку "операторов", на вход очередного оператора подаётся выход из предыдущего.
Профит - удобно составлять логику, ошибки всегда прокидываются до получателя, можно остановить выполнение на любом этапе.
(я это сделал в виде worker - operator(s) - receiver (операторы обычно тоже worker'ы).

Кароче, суть "проблемы" открылась при добавлении оператора, который бы превратил массив в последовательность единичных элементов (flatMap).

Оператор наследуется от базового Chunk<TIn,TOut>{ ... }
т.е. у него есть тип входных данных и тип выходных.
Прицепляемый к нему оператор должен на вход получить выход от текущего, а на выходе может иметь любой тип, т.е. Chunk<TOut,TOut2>

Так вот, как из шаблонных типов вытащить массив?

Я не долго думая написал для нашего flatMap'а такой вариант:
Chunk<TOut[],TOut>
В надежде, что если мы на вход даём Integer[], то TOut распознается как Integer.

И это так, но только в рамках самого класса!

В каждом операторе есть входной метод
void onReceive<TIn data>{ ... }
в рамках этого метода по описанному выше типу данных я смог нормально пробежать по массиву:
void onReceive<TOut data>{ // здесь TOut, т.к. на вход берём быход от предыдущего оператора
  for (TOut i : data){
    sendResult(i); // пересылаем каждое значение в nextChunk
  }
}
Всё хорошо, тут наш Integer.

Однако, когда к этому оператору хотим прицепить следующий, у которого на входе должен быть штучный Integer,
то получаем ошибку нестыковки типов - "на входе ожидается массив Integer[]".

Т.е. наш TOut вне самого класса оператора расползнаётся как массив.
Но тогда логично, что конструкция <TOut[],TOut> должна развернуться в <Integer[][],Integer[]> внутри класса, но этого не происходит.
И это немного сломало мне мозг.
^ Ради этой инфы и написан этот пост.

В итоге я добавил шаблонный тип TOut2 к этому оператору
public <TOut2> Chunk<TOut,TOut2> flatMap() { ... }
и убрал признак массива в шаблонном типе TOut
(проверка на массив или итератор делается через instanceof;
не фэншуй? зато работает, и я пока на экспорт не планирую отдавать, а мне норм такой вариант).

при использовании теперь нужно явно указывать тип
new CallChain()
  .someWorker()
  .<Integer>flatMap()
  .someOperator()
  .....
чуток неудобно, но я лучшего решения не придумал.

кому интересен весь код - гитхаб.

Да, я смотрел исходники RxJava, но нихрена не понял, умеют же люди писать такие заморочки.

Последний раз редактировалось Жека, 20.02.2017 в 07:12.
(Offline)
 
Ответить с цитированием
Старый 16.03.2017, 16:09   #11
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,342
Написано 473 полезных сообщений
(для 852 пользователей)
Ответ: Полезные находки

Проверка нажатия кнопки HOME.

Переопределяем метод активити:
@Override
protected void onUserLeaveHint(){
    
log("Home Button Pressed");
    
super.onUserLeaveHint();

(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
St_AnGer (16.03.2017)
Старый 18.03.2017, 15:02   #12
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,342
Написано 473 полезных сообщений
(для 852 пользователей)
Ответ: Полезные находки

Переопределение методов в момент создания класса

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

Например, нужно запретить клик и выделение по клику в дефолтном андроидовском адаптере.
Переопределяем нужный метод непосредственно при создании класса:
String[] lines message.split(".\n");

ArrayAdapter<Stringadapter = new ArrayAdapter<String>(Main.getContext(), // контекст
    
android.R.layout.simple_list_item_1// resId
    
lines){ // данные

    
@Override
    
public boolean isEnabled(int position) { // запрещаем выделять нажатие
        
return false;
    }
}; 
Естественно, для финальных классов так делать нельзя.
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +1, время: 14:37.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com