вторник, 18 августа 2015 г.

Офіційний реліз фінальної версії Android M - Marshmallow "Зефір"




Android 6.0 Marshmallow
Не важливи чи ви їх любите прямо з коробки чи з хрусткими піджареними на вогні з золотою кіркою та розтопленою серединою, чи в пухкій формі, хто ж не любить зефір? Ми точно його любимо! З запуску розробницької версії M Developer Preview на Google I/O в травні, ми були задоволені вашим вкладом та відгуками. Сьогодні разом з фінальною версією оновлення Developer Preview, ми представляємо офіційний Android 6.0 SDK та відкриваємо Google Play для публікації ваших додатків для нового API level 23 в Android Marshmallow.

Приготуйте ваші додатки до Android Marshmallow


воскресенье, 16 августа 2015 г.

Що робити, коли користувач не надав вам доступ в Android M

Порада професіонала +Wojtek Kaliciński

Новенька версія Android M Developer Preview 2 включає в себе методи для обробки надання дозволів (Permissions): Activity.shouldShowRequestPermissionRationale().
Він інформує ваш додаток, про необхідність надати інформацію про дозвіл, на який іде запит, до того як буде показаний сам діалог запиту дозволу на ту чи іншу функцію.

При першому запуску додатку метод повертає false, таким чином ви можете в той же час запитати на дозвіл необхідного в даний момент. Якщо користувач вже відмовився надавати дозвіл, метод поверне true. У випадку, якщо ви вважаєте за необхідне відобразити пояснення перед викликом діалогу запиту дозволу знову, ви маєте мати на увазі, що слід робити тільки у випадку, якщо дозвіл не самопояснюваний.


пятница, 14 августа 2015 г.

Погода на Марсі з використанням бібліотеки Volley




Final product image
Ось, що ми отримаємо в результаті

У цій статті, я покажу вам один з можливих практичних способів використання знань, які ви здобули в попередній статті про бібліотеку Volley. Ми будемо створювати додаток для відображення погоди на Марсі, використовуючии інформацію зібрану ровером Curiosity, яка тепер доступна кожному завдяки NASA через {MAAS} API.
Спочатку, ми налаштує проект в Android Studio та спроектуємо користувацький інтерфейс. Далі ми будемо конструювати ядро додатку за допомогою Volley. Зважаючи на те, що кожен додаток, так чи інакше, оперує зображеннями, я покажу, як стягнути випадкове зображення використовуючи Flickr API. Ми будемо завантажувати зображення за допомогою Volley, в основному через її чудову систему кешування. І в кінці,  ми додамо декілька прикрашальних функцій, щоб надати нашому додатку ефектності.

четверг, 13 августа 2015 г.

Знайомство з Volley

Volley - це бібліотека для роботи з мережею, розроблена копанією Google та представлена протягом презентації Google I/O в 2013 році. Вона була розроблена через відстутність в Android SDK класу здатного працювати без втручання в UX.
До випуску бібліотеки Volley, єдиними доступними варіантами для розробників були Java class java.net.HttpURLConnection та Apache org.apache.http.client,так розробники могли реалізовувати роботу між клієнтом та сервером для RESTful систем.
Відклавши в бік той факт, що ці два класи не звільняють вас від винекнення багів, слід відмітити, як все, що проходить поза простими HTTP транзакціями має бути написано заново. Якщо ж вам потрібно було закешувати зображення чи оптимізувати запити, ви мали розробляти його з нуля.
На щастя, зараз бібліотке Volley, повністю задовольняє такі потреби.

вторник, 11 августа 2015 г.

TabLayout: з бібліотеки підтримки Android

tab_layout_demo_app_logo
Сьогодні поговоримо про TabLayout.
TabLayout забезпечує можливість створення горизонтальних вкладок.

Де заховати пароль в додатку на Android

Я хотів би пройти крізь декілька напівреалістичних прикладів та пояснити, що приховано за деякими з стратегій, та чому вони можуть бути не такими ефективними як ви могли б сподіватись.
Огляд не охоплює всі можливі варіанти, ми розгляними тільки декілька найбліьш популярних та доступних із способів збереження secret, і, що може піти не так:

  1. Вбудовувати в файл strings.xml
  2. Приховати у вихідному коді
  3. Приховати в BuildConfigs
  4. Використовувати Proguard
  5. Замасковані/Зашифровані файли String
  6. Приховати в Native Libraries



понедельник, 3 августа 2015 г.

Централізація бібліотек підтримки в Gradle

Працюючи з мульти-модульними проектами, часто корисно централізувати залежності, особливо це відноситься до бібліотек підтримки.

Правильним шляхом вважається розділяти білд-файли gradle, записуючи таким чином:

вторник, 21 июля 2015 г.

Стилізація Snackbar

Вітаю, ми повертаємось до наступника діда-Toast нового молодіжного і сучасного Snackbar. Сьогодні ми розглянемо декілька надзвичайно вражаючих можливостей з бібліотеки підтримки (design support library) і собливо Snackbar.
Stay tuned!

Стилізація Snackbar

В попередній публікації, ми розібралися, як користуватися Snackbar, а сьогодні ми поглянемо як можна кастомізувати snackbar та відобразити його іншим кольором, стилізованим під наші потреби, щоб це мало значення для користувача, наприклад відображати червоним помилки.
Виглядатиме наш додаток так:

Styling snackbar

Styling snackbar 1

Робота з мережею в Android: OkHttp, Volley та Gson

Програмуючи під Android є речі, які ви просто не можете уникати: робота з мережею (networking). Що б це не було: завантаження зображення, робота з API чи просто 1 байт з інтернету - все це робота з мережею.
Враховуючи те на скільки робота з мережею є важливою та фундаментальною в розробці, одне з основних питань з якими стикаються Android розробники це вибір правильного рішення для реалізації конкретної задачі.
Причиною того, що нам доводиться використовувати сторонні бібліотеки є неспроможність android фреймворку реалізувати нормально роботу з мережею, ще з давніх часів, коли панували такі динозаври як Froyo та Gingerbread, доводилося писати раз за разом один і той же код. Враховуючи динаміку з якою розвивався Android було логічно спробувати написати щось своє, чи використати готове рішення від сторонніх розробників, які все розвивались і розвивались.

In the old days networking on Android was a nightmare, nowadays the problem is to find out which solution best fits the project necessities.
В цій статті ми поговоримо про конкретні рішення на базі OkHttp, Volley та Gson.

Для вдалого експерименту припустимо, що для обміну даними з сервером ви використовуєте JSON, працюєте в Android Studio з Gradle.
OkHttp це достатньо новий, швидкий та ефективний Http клієнт, який підтримує HTTP/2 та SPDY і виконує за вас безліч однотипної роботи. Прекрасний спосіб зрозуміти наскільки важко працювати з мережею це поглянути на все те що OkHttp для установки звязку, кешуваання і т.д. OkHttp працює як транспортний рівень.
OkHttp використовує Okio, бібліотекою, що доповнює  java.io and java.nio та допомагає легше отримати доступ, зберігати та користуватися вашою інформацією.
І OkHttp, і Okio розроблені хлопцями з Square.
Volley це бібліотека, що полегшує роботу з побутовими задачами мережі. Бере на себе запити, завантаження, кешування, поточність, синхронізацію та інші штуки. Легко працювати з JSON, зображеннями, кешем, текстом та дозволяє кастомізованим.
Volley була спроектована для RPC стилю роботи з мережею, що популяризує UI. Являється прекрасною альтернативою для простих, коротких задач.
Volley за замовчуванням використовується на транспортному рівні як Apache Http stack на Froyo та HttpURLConnection stack на Gingerbread і вище. Біда в тому, що є деякі проблеми з http stack на різних версіях Android.
Volley дає можливість простіше налаштувати OkHttp як транспортний рівень.
Volley була розроблений компанією Google.
Gsonце бібліотека серіалізації та десеріалізації JSON, що використовує рефлекцію для попляризації вашої Java моделі об'єктів з об'єктів JSON.
Gson була розроблений компанією Google.

понедельник, 20 июля 2015 г.

Кнопка Google Plus в додатках на Android

title_plus_one_button
Поговоримо про інтеграцію кнопки Google’s +1 з додатками на базі Android.

Перше питання, - "Навіщо?". Все заради популярності вашого додатку. Дана кнопка допоможе підвищи рейтинг в Play Store.
Перш за все, потрібно додати бібліотеку у ваш проект або ж залежність у файл gradle.

EditText плаваючі заголовки: Бібліотека підтримки Android

edittext_floating_labels_title
Сьогодні, поговоримо про EditText Floating Labels в Android додатках.

Новий TextInputLayout дозволяє нам запаковувати EditText для можливості показувавти плаваючі заголовки над полями EditText. Такж ми маємо можливість показувати помилки під полем EditText. Коил форма EditText в фокусі, підказка піднімається над view в ліву частину.
Перш за все нам необхіжно додати бібліотеку або прописати залежність в файлі gradle.

четверг, 16 июля 2015 г.

Android Studio на SSD

Маю ноутбук HP envy 4-1152er з SSD диском, але на жаль він всього-на-всього на 32GB і так вийшло, що Android Studio займає занадто багато місця. Якщо у вас така ж проблема то зараз ви дізнаєтесь як з цим боротися.
Android Studi встановлюємо на диск D.

SDK

1. SDK переносимо на диск D, в зручну для вас директорію, в мене це D:\Program Files\android-sdk.
2. В налаштуваннях за допомогою пошуку знаходимо наш sdk і змінюємо на нову.
3. Зберігаємо налаштування:


понедельник, 6 июля 2015 г.

Вступ до RxJava для Android #1

Сам я мав деякі сумніви щодо реактивного програмування і вирішив докладно розібратися в даному полі, а заодно і донести свої знання до громади, може комусь і знадобиться.

RxJava - це бібліотека реактивного програмування, що дозволяє вам представити будь-що у вигляді асинхронного потоку даних, який може бути створений в будь-якому потоці, може бути функціонально трансформований та бути використаний чим завгодно.
Реактивне програмування - парадигма програмування, орієнтована на потоки даних і поширення змін. Це означає, що повинна існувати можливість легко висловлювати статичні і динамічні потоки даних, а також те, що виконувана модель повинна автоматично поширювати зміни крізь потік даних.
Відмовостійкість, орієнтованість на події і масштабованість - чотири принципи нині популярного реактивного програмування. Саме дотримуючись їх створюється backend великих систем з одночасною підтримкою десятків тисяч з'єднань.
Простота, гнучкість і розширюваність коду - принципи, які можна закріпити за реактивним UI.


Snackbar - логічний фінал Toast


Сьогодні поговоримо про компонент з Android design support library під назвою “Snackbar”.

Snackbar - логічний фінал Toast

“Providing lightweight, quick feedback about an operation is a perfect opportunity to use a snackbar.”
Snackbar компонент доступний в design support library. Використовуючи Snackbar, ми можемо показувати швидкі повідомлення в нижній частині екрану (в осносному). Даний компонент дуже схожий на Toast, але більш гнучкий:
  • Він автоматично зникає після таймауту чи після взаємодії з користувачем.
  • Опціонально містить в собі дію.
  • Можна відмінти FAB свайпом з екрану.
  • На відміну від Toast перекриває екран, а не накладається
  • Являється частиною UI та є контексозалежним.
  • Тільки один snackbar може відображатися в один проміжок часу.
Snackbar успадквує ті ж методи та атрибути що й Toast, наприклад LENGTH_LONG та LENGTH_SHORT для налаштування тривалості.

Синтаксис:

Поглянемо на маленький приклад:




Snackbar.make(view, message, duration)
       .setAction(action message, click listener)
       .show();
Методи:
  • make() – Змусити Snackbar відображати повідомлення;
  • setAction() – Налаштувати дію;
  • show() – Показати Snackbar;
Арибути:
  • Перший параметр методу make() це view, snackbar спробує знайти батьківський view для утримання snackbar. Snackbar прогляне все дерево шарів і закріпиться на верхньому.
  • Як вже згадувалось раніше, аргумент тривалості такий же як і в Toast, але тільки LENGTH_SHORT чи LENGTH_LONG, так тут не можна явно вказати тривалість.

Приклад:









Snackbar.make(rootlayout, "Hello SnackBar!", Snackbar.LENGTH_SHORT)
       .setAction("Undo", new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               // Perform anything for the action selected
           }
       })
       .show();

Тут, кореневий шар (layout) framelayout має FAB, який в свою чергу викликає Snackbar.
Натисніть на FAB та перевірте результат:

Snackbar framelayout

Так, все працює але на жаль не так як мало б взаємодіяти з UX. Насправді снекбар мав би зсунути FAB трох вверх, як зображено нижче, а також сказано в документації:
Having a CoordinatorLayout in your view hierarchy allows Snackbar to enable certain features, such as swipe-to-dismiss and automatically moving of widgets like FloatingActionButton.
Ми поговоримо про CoordinatorLayout в наступній статті.

Snackbar with CoordinatorLayout

Налаштування Snackbar

Ми можемо використовувати деякі додаткові налаштування в snackbar наприклад: setActionTextColor та setDuration:









Snackbar.make(rootlayout, "Hello SnackBar!", Snackbar.LENGTH_SHORT)
       .setAction("Undo", new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               // Perform anything for the action selected
           }
       })
       .setActionTextColor(R.color.material_blue)
       .setDuration(4000).show();
Завантажити приклад можна за посиланням: https://github.com/PareshMayani/DesignSupportLibraryExamples
Джерела:

Підсумкт

Ми трохи поговорили про Snackbar, що функціонує подібно до TOAST але з більш ширшими та гнучкішими налаштуваннями, він може також вміщувати в собі єдину дію та бути відхиленим простим свайпом з екрану або автоматично після закінчення виділеного інтервалу часу, чи навіть після взаємодії з користувачем.
Ми безумовно побачимо більше ефектів та поведінки завдяки підключенню CoordinatorLayout, але це буде в наступній статті.

source

среда, 24 июня 2015 г.

Про Gradle: #2 Синтаксис

В першій частині ми говорили про таски та їх стадії життєвого циклу. Але вже після публікації я зрозумів що перед ти як ми поринемо в особливості Gradle важливо зрозуміти з чим саме ми маємо справу - зрозуміти його синтаксис та перестати боятися вигляду файлу build.gradle. І за допомогою цієї статті я спробую заповнити дану прогалину.

Синтаксис

Скрипти Gradle написані мовою Groovy, тож до того як ми почнемо їх аналізувати, я хотів би зачепити (коротко) деякі ключові концепти Groovy. Синтаксис Groovy деяким чином схожий на  Java, тож сподіваюсь у вас не буде великих проблем з його розумінням.
Якщо з Groovy почуваєтесь на ти - не бачу проблем щоб не пропустити декілька абзаців.
Є один дужу важливий нюанс в Groovy, який вам необхідно зрозуміти для повного розуміння скриптів Gradle - Closure.

Closures

Closure - це ключовий компонент який нам необхідно зрозуміти перед освоєнням Gradle. Closure це незалежний блок коду, який може приймати аргументи, повертати значення та бути присвоєним змінній. Це такий собі мікс між інтерфейсами Callable, Future, та покажчиком на функцію.
По суті це блок коду, який виконуються при виклику, а не при стоворенні. Подивимось на простй приклад Closure:

def myClosure = { println 'Hello world!' }

//виелик closure
myClosure()

#output: Hello world!

Або тут closure який приймає параметр:

def myClosure = {String str -> println str }

//виклик closure
myClosure('Hello world!')

#output: Hello world!

Або якщо closure приймає тільки один параметр, він може виглядати як it:

def myClosure = {println it }

//виклик closure
myClosure('Hello world!')

#output: Hello world!

Чи коли closure приймає декілька параметрів:

def myClosure = {String str, int num -> println "$str : $num" }

//виклик closure
myClosure('my string', 21)

#output: my string : 21

Крім того, тип аргументу опціональний, далі бачимо спрощений приклад без типів:

def myClosure = {str, num -> println "$str : $num" }

//виклик closure
myClosure('my string', 21)

#output: my string : 21

Ще одна гарна можливість closure може посилатися на змінні з поточного контексту(читай класу). За замовчуванням, поточний контекст - це клас створений в даному closure:

def myVar = 'Hello World!'
def myClosure = {println myVar}
myClosure()

#output: Hello world!

Ще одна можливість в тому що поточний контекст для closure може бути змінений викликом Closure#setDelegate(). Ця можливість буде дуже важливою трохи пізніше:

def myClosure = {println myVar} //Зсилаємося на myVar з класу MyClass 
MyClass m = new MyClass()
myClosure.setDelegate(m)
myClosure()

class MyClass {
    def myVar = 'Hello from MyClass!'
}

#output: Hello from MyClass!

Як ви могли помітити, в момент коли ми створюємо closure, змінна myVar ще не існує. І тут це повністю нормально - вона має бути присутньою в контексті closure в момент виконання.
В цьому випадку я модифікував теперішній стан контексту для closure прямо перед тим як виконати його, тож myVar доступна.

Передача closure як аргумента

Користь від closures - в можливості передавати closure іншим методам, що допомагає нам відокремити логіку від вииконання.
Раніше ми також викоритсовували closure для передачі екземпляру іншого класу. А тепер переглянемо інші методи closure:
  1. Методи приймає один парамет - closure
    myMethod(myClosure)
  2. Якщо метод приймає один парамет - дужки можна не використовувати
    myMethod myClosure
  3. Внутрішній closure
    myMethod {println 'Hello World'}
  4. Метод приймає два параметри
    myMethod(arg1, myClosure)
  5. Те ж що й 4 
    myMethod(arg1, { println 'Hello World' })
  6. Якщо останній параметр closure - то його можна винести
    myMethod(arg1) { println 'Hello World' }
Зверніть увагу на пункти 3 та 4. Нічого не нагадує? Це ж і є Gradle скрипти.

Gradle

З синтаксисом трохи ознайомилися, тепер розберемося як же, все-таки, це відноситься до скриптів Gradle? Подивимось на простий приклад скрипту Gradle і постараємось його зрозуміти:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.3'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

Ви тільки подивіться! Знаючи синтаксис Groovy ми розуміємо що саме коїться в даному прикладі!
  • Метод buildscript що приймає значення closure:
    def buildscript(Closure closure)
  • Метод allprojects приймає closure:
    def allprojects(Closure closure)
...і так далі.
Прекрасно, але ця інформація сама по собі насправді не допомагає... Тепер треба визначити де саме це все виконується.
А відповіддю буде - Project

Project

Це ключ для розуміння скриптів Gradle:
Всі вирази на вищому рівні в скрипті build заделеговані в екземплярі Project
Це означає, що Project - є початковою точкою.
Спробуємо знайти метод buildscript.
Якщо будемо шукати buildscript - ми знайдемо блок скрипту buildscript {}. Секундочку.. А що ж це таке, чорт забирай??? Згідно з документацією:
Блок скриптів це виклик методу який бере closure як параметр
Добре! Знайшли! Ось що насправді трапляється, коли ми викликаємо buildscript { ... } - ми запускаємо метод buildscript який приймає Closure.
Якщо продовжимо читати документацію по  buildscript то дізнаємось: Delegates to:
ScriptHandler from buildscript
. Це означає, що обсяг виконня для closure, який ми передаємо як вхідний параметр, буде змінений на ScriptHandler. В нашому випадку ми передаємо closure який запускає метод repositories(Closure) і метод dependencies(Closure). З того часу як closure заделегований в ScriptHandler, спробуємо знайти метод dependencies в класі ScriptHandler.
І ми його знаходимо - void dependencies(Closure configureClosure), щ згідно з документацією, конфігурує залежність для скрипту. Тут ми натикаємось на ще один термін: Executes the given closure against the DependencyHandler. Що означає те ж саме що й "lделегується до [чогось]" - цей closure буде виконано в рамках іншого класу (в нашому випадку - DependencyHandler)
"delegates to [something]" та "configures [something]" - 2 вирази, що мають одне значення - closure буде виконано в зазначеному класі.
Gradle постійно використовує стратегію делегатів, отже важливо тут розуміти термінологію.
Для повноти, давайте подивимось, що трапиться коли ми виконаємо closure {classpath 'com.android.tools.build:gradle:1.2.3'} в контексті DependencyHandler. Згідно з документацією цей клас конфігурує залежності і має виглядати як:
<configurationName> <dependencyNotation1>
Отже в нашому closure ми зконфігуруємо classpath для використання com.android.tools.build:gradle:1.2.3 як залежності.

Блоки скриптів

За замовчуванням, існують попередньо встановлені блоки в Project, але плагіни Gradle дозволяють додавати нові блоки самостійно!
Це означає, що якщо ви бачите щось на кшталт something { ... } на верхньому рівні вашого білд скрипту і ви не можете знайти ні блок скриптів, ні метод, який приймає closure в документації - схоже на те, що один з плагінів, які ви використовувал, додав цей блок скриптів.

android Script block

Подивимось на скрипт білду Android app/build.gradle за замовчуванням:
apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.trickyandroid.testapp"
        minSdkVersion 16
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
Як ми можемо бачити, здається, що тут має бути методи android який приймає Closure як параметр. Але якщо ми спробуємо знайти такий метод в документації Project то не знайдемо нічого подібного. Причина проста - такого методу просто не має :)
Якщо придивитися до скрипту build - ви побачите що перед запуском методу android - ми застосовуємо плагін com.android.application! Це і є відповідь на наше запитання! Android наслідує Project з блоком скриптів android (що є просто методом, який приймає Closure та делегує його до lкласу1 AppExtension ).
Але де нам знайти документацію плагінів Android? ЇЇ можна завантажити з офіційного веб сайту Android Tools.
Якщо ми відкриємо документацію AppExtension то знайдемо всі методи та атрибути, які необхідні.

Вправа

Спробуємо самотушки щось переналаштувати, бо ми тепер знаємо як це робиться :)
В AppExtension є блок скриптів testOptions який делегує Closure в клас TestOptions. Перейдемо до класу TestOptions ми бачимо дві властивості: reportDir та resultsDir. Згідно з документацією, reportDir несе відповідальність за місце розташування протоколу тестування. Змінимо його.

android {
......
    testOptions {
        reportDir "$rootDir/test_reports"
    }
}

Ми використали властивість rootDir з класу Project що вказує на корінь папки проекту.
Тож якщо зараз ми запустимо ./gradlew connectedCheck, звіт про тестування відправиться в папку[rootProject]/test_reports .
На практиці цього краще не робити.

Happy gradling!

Source.

вторник, 23 июня 2015 г.

Про Gradle: #1 Таски

Цією публікацією, я б хотів розпочати серію статей пов'язаних з Gradle, ох, хотілося б мені знати це, коли я почав писати скрипти на Gradle.
Сьогодні ми поговоримо про таски в Gradle, а особливо про їх конфігурацію та виконання частин таску. Зважаючи на те, що багато термінів можуть виявитися невідомими більшості читачів, буде набагато легше приводити приклади. По суті ми постараємось виявити в чому різниця між цими трьома прикладами:

task myTask {
    println "Hello, World!"
}

task myTask {
    doLast {
        println "Hello, World!"
    }
}

task myTask << {
    println "Hello, World!"
}

Моя основна ціль написати таск, який виводить на екран текст "Hello, World!" при виконанні.
Коли я починав розбиратися з Gradle, першими з моїх варіантів, була реалізація подібним чином:

task myTask {
    println "Hello, World!"
}

Зараз, спробуємо запустити таск!

user$ gradle myTask
Hello, World!
:myTask UP-TO-DATE

Здається все працює! Ми бачимо "Hello, World!".
АЛЕ! Воно працює не так, як ми очікували. І ось чому. Давайте-спробуємо викликати gradle tasks і побачимо, які інші такски в нас є:

user$ gradle tasks
Hello, World!
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
..........

Секундочку! Чому наше "Hello, World!" вивелось на екран? Ми ж просто викликали tasks, Чому ж запустився наш таск!
Причина чому це трапляється в тому, що таски Gradle матюь 2 стадії життєвого циклу:
  • Стадія конфігурації
  • Стадія виконання
Насправді, я не був дуже точний в термінології, але ця аналогія допомогла мені зрозуміти, що ж таке таски.
Справа в тому, що Gradle має сконфігурувати всі таски зазначені в скрипті перед тим як білд буде запущено. Немає значення, якщо деякі таски будуть запущені - вони все-одно мають бути сконфігуровані.
Знаючи це, як нам знати, яка частина таску виконується під час конфігурації, а яка під час виконання?
Відповіддю є - частина вказана у верхній частині таску - це і є секція конфігурації таску:

task myTask {
    def name = "Pavel" //<-- this is evaluated during configuration
    println "Hello, World!"////<-- this is also evaluated during configuration
}

Ось чому, коли ми викликали gradle tasks то було видно текст "Hello, World!" - це була виконана наша частина конфігурції. Але це не те, що нам було потрібно - нам потрібно що текст "Hello, World!" був надрукований, коли ми явно викликаємо таск.
То як нам сказати Gradle зробити щось коли наш таск буде виконуватись?
Щоб зробити це нам необхідно зазначити дію. Найлегший спосіб зробити це через Task#doLast() метод:

task myTask {
    def text = 'Hello, World!' //configure my task
    doLast {
        println text //this is executed when my task is called
    }
}

Тепер наш "Hello, World!" текст буде виведено тільки тоді, коли буде явно введена команда gradle myTask
Круто, тепер ми знаємо як зконфігурувати і змусити наш таск виконувати ту роботу, яку ми йому задамо тільки тоді, коли ми його викликаємо. Залишився тільки третій варіант, що використовує символ "<<"?:

task myTask2 << {
    println "Hello, World!" 
}

Насправді, це просто коротка версія від doLast. Буде виконано теж саме, коли ми напишемо:

task myTask {
    doLast {
        println 'Hello, World!' //this is executed when my task is called
    }
}

Отже, тепер все знаходиться в блоці виконання, я не можу зконфігурувати мій таск таким же чином отже ми це зробимо завдяки конструкції doLast (це досі можливо, але трохи по-іншому). Стає зрозуміло, що цей спосіб буде незамінними при невеликих таксках без блоку конфігурації, але якщо ви маєте щось більше ніж "Hello, World!" - можливо вам буде в нагоді doLast.

Happy gradling!

Source.

понедельник, 22 июня 2015 г.

Залізна людина тепер реактивна: RxJava

Дана стаття присвячена перевагам, що можуть бути надані нашим проектам деякими функціональними штрихами.
Фреймворки типу RxJava та ReactiveX можуть легко вправитися з середовищами, що працюють у фоні та в UI потоці.
Ця стаття також фокусується на тому, як оператори можуть мінімізувати час на загальну розробку завдань, реактивні розширення пропонують широкий спектр операторів, щоб зробити ваше життя простіше.
Як завжди, код на Github, не соромтеся коментувати, відкрити питання або скаржитися!.

RetroLambda

Інколи, у великих додатках, розроблених з Java, або великих фреймворках як android дуже важко, чи навіть неможливо (android) використовувати можливості Java 8 такі як лямда-вирази
Retrolambda це бекпорт, що з'явився для вирішення даної проблеми, переклад байткодів Java 8 на попередні версії Java дає можливість користуватися лямда-виразами та іншими можливостями нової платформи.

Retrolamda може працювати з Gradle та Maven, я обрав Gradle так як він йде в комплекті з Android Studio, для використання вам досить додати в корінь файлу build.gradle плагін Retrolambda та застосувати у вашому модулі build.gradle, встановити рівень мови на 1.8 в Android Studio і все готово.

build.gradle (root)
    dependencies {
        classpath 'me.tatarka:gradle-retrolambda:3.1.0'
{ваш модуль}/build.gradle
    apply plugin: 'me.tatarka.retrolambda'

    android { 

        ...

        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    }
}

Retrolambda дозволяє вам писати менше шаблонного коду, а також робить код зрозумілішим. У цьому прикладі написаному Den Lew ви можете побачити різницю.

Без використання RetroLambda
Observable.just("Hello, world!")
    .subscribe(new Action1<String>() {
        @Override
        public void call(String s) {
              System.out.println(s);
        }
    });
З використанням RetroLambda
Observable.just("Hello, world!") .subscribe(
    s -> System.out.println(s)
);

А тепер на прикладі додатку Месники:

mCharacterSubscription = mGetCharacterInformationUsecase
    .execute().subscribe(
        character -> onAvengerReceived(character),
        error     -> manageError(error)
    );

mComicsSubscription = mGetCharacterComicsUsecase
    .execute().subscribe(
        comics -> Observable.from(comics).subscribe(
            comic -> onComicReceived(comic)),
        error  -> manageError(throwable)
    );

ReactiveX

ReactiveX - це колекція з проектів з відкритим вихідним кодом серед їх основних принципів є шаблон проектування Спостерігач, шаблон Ітератор та функціональне програмування.
ReactiveX також має API для асинхронного програмування, з цим фреймворком насправді дуже легко реалізовувати завдання асинхронно.

ReactiveX як асинхронний клієнт

Гарна штука, що користуєчись ReativeX можна створювати повністю асинхронний API чи клієнт, а потім вже при реалізації вирішувати, який код буде працювати асинхронно чи в окремому потоці (Thread) чи синхронно.  
Таким чином, ми маємо спостережуваний API, а не блокуючий API.

public interface Usecase<T> {

    Observable<T> execute();
}
public interface Repository {

    Observable<Character> getCharacter (final int characterId);

    Observable<List<Comic>> getCharacterComics (final int characterId);
} 
 

Чим же насправді є RxJava

Клас Observable створює об'єкт чи серію об'єктів ці об'єкти отримуються методом Observer, що наледить класу "Observable".


Необхідно щоб Observer був прив'язаний до Observable, в іншому випадку Observer не видасть нічого. Коли Observer пррив'язаний, об'єкт типу Subscription створюється, він  використовується для відв'язування Observable, це крисно при роботі з Activity та Fragment в методах onStop чи onPause, наприклад.

mCharacterSubscription = mGetCharacterInformationUsecase
    .execute().subscribe( ... );
@Override
public void onStop() {

    if (!mCharacterSubscription.isUnsubscribed())
        mCharacterSubscription.unsubscribe();

    if (!mComicsSubscription.isUnsubscribed())
        mComicsSubscription.unsubscribe();
} 
 
Коли Observer прив'язаний до Observable він має отримати три методи.
  • onNext (T) метод для отримання об'єктів позначиених 'Observable' помилковими
  • onError (Exception), метод який викликається при виявленні помилок
  • onCompleted(), метод який викликаєть коли Observable завершує створення об'єктів.

Обожнюю цю картинку:)

Компоненти зв'язку

Тепер подивимось на те як можна використовувати GetCharacterInformationUsecase. Варіаннти реалізації інтерфейсу Usecase <T>:

public interface Usecase<T> {

    Observable<T> execute();
}
 
Коли usecase запущено - повертається об'єкт типу Observable, корисна можливість бути зв'язаним з observable та операторами з меншими зусиллями, ми ще побачимо велику силу операторів в подальшому.
Коли ми запускаємо GetCharacterInformationUsecase ми говоримо нашому репозиторію запросити у відведеного джерела даних:

@Override
public Observable<Character> execute() {

    return mRepository.getCharacter(mCharacterId);
        // .awesomeRxStuff();
}
 
AvengerDetailPresenter буде нашим Observer в даному випадку буде тим хто піписується до подій надісланих Observable, це робиться за допомогою методу subscribe, що зв'язує Observer з Observable.
onNext та onError реалізовані для управління результатом операції. Метод onCompleted не реаалізований в даному випадку так як не є необхідним.

    mCharacterSubscription = mGetCharacterInformationUsecase
        .execute().subscribe(
            character   -> onAvengerReceived(character),
            error       -> manageError(error));

Retrofit & RxJava

Retrofit зі Square, RxJava підтримує методи типу rx. Observable так що запити можна робити за допомогою Observers редагувати та трансформувати.
Ви маєте бути на сторожі в залежності від того де використовується, Retrofit виконує запити в потоці де ваш Observable виходить, отже якщо ви будете його викликати в UI потоці (activity чи Fragment) отримаєте помилку.

Посилання










Source.

воскресенье, 21 июня 2015 г.

Можливо ви не знали: onResumeFragments

Вся суть в одному реченні: якщо ви використовуєте підкласи FragmentActivity (такі як AppCompatActivity) і думаєте над якимись транзакціями в onResume, краще зробіть це в onResumeFragments.
Якщо ви відчуваєте, що бачите деякі прогалини чи неточності в своїх знаннях, запрошую до читання. В іншому випадку сподіваюсь здивувати вас наступного разу.

Все ще тут? Добре.
В чому різниця між onResume та onResumeFragments? З документації для FragmentActivity.onResume:

Dispatch onResume() to fragments. Note that for better inter-operation with older versions of the platform, at the point of this call the fragments attached to the activity are not resumed. This means that in some cases the previous state may still be saved, not allowing fragment transactions that modify the state. To correctly interact with fragments in their proper state, you should instead override onResumeFragments().

Простіше кажучи, ви не можете бути впевнен, що існуючий фрагмент актівіті буде відновлений в актівіті onResume(), і краще уникнути транзакцій фрагментів до onResumeFragments, поки їх стан не поновлено і вони повністю не відновлені.
Притримуючись сказаного ви можете уникнути IllegalStateException, який Android викидає кожного разу як ви намагаєтесь виконати транзакцію з фрагментом після того/, як його стан був збережений (через onSaveInstanceState). Якщо актіві фрагменту знищено і перестворено, ви втратите всі вподальному збережені дані. Для більш повного та детального пояснення, пропоную прочитати статтю, Alex Lockwood's "Fragment Transactions & Activity State Loss".
Правду кажучи, я дізнався про onResumeFragments задовго після того як дізнався про фрагменти та транзакції між ними. Більшість матеріалів по життєвому циклу актівіті опускає його оскільки він існує тільки в FragmentActivity в біблітоці підтримки (FragmentActivity), а не в класі SDK актівіті. Однак, onResumeFragments краще, все ж таки, знати.
Після всйого сказаного, хочу додати, що все ж кращу уникати транзакцій між фрагментамив життєвому циклі актівіті настільки наскільки це можливо і особливо в onResume/onResumeFragments це скоріше гарна підказка для вашої бізнес логіки та UI/UX аніж правило.

Зустрінимось.