🏆 Рейтинг ІТ-роботодавців 2018: вже зібрано більше 13 000 анкет. Оціни свою компанію!
×Закрыть

Логування Android-застосунку з XLogger

Разом з іншими Android-інженерами в CloudMade ми вирішили покращити логування в нашому Android-застосунку. Визначили шари, які хотіли б логувати, а потім створили різні теги для кожного шару. Було важливо логувати все, що ми встановлюємо в Android Data Binding ObservableField (примітиви, такі як ObservableInt, ObservableFloat та ObservableField ).

Що таке Android Data Binding

Android Data Binding дає спосіб пов’язати інтерфейс користувача з бізнес-логікою, що дозволяє користувачеві оновлювати значення інтерфейсу без ручного втручання. Це зменшує кількість коду в бізнес-логіці для синхронізації інтерфейсу, коли надходять нові дані. Data binding — це один з компонентів архітектури Android, запропонований Google.

Вступ

Логування є невід’ємною частиною розробки програмного забезпечення. Воно надає розробникам та командам підтримки можливість побачити, як дійсно працює код програми.

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

Визначення проблеми

У нас є ViewModel з ObservableField, і ми хотіли логувати встановлення кожного нового значення в нього:

public class ViewModelMainActivity {

   public android.databinding.ObservableField<String> messageObservable = new ObservableField<>();

}

Однією з основних проблем була необхідність не вносити багато змін у клієнтський код. Ми не хотіли створювати обгортки для кожного ObservableField, такі як ObservableInt, ObservableFloat, ObservableField тощо). Ми також не хотіли перевизначати в них метод set() і ініціалізувати ним кожен ObservableField, який уже мали в програмах в кожній ViewModel. Отже, ми вирішили створити власну бібліотеку, яка зробить це за нас — XLogger!

Налаштування бібліотеки

Щоб використовувати XLogger, додайте залежність до build.gradle вашого модуля і синхронізуйте проект.

implementation 'com.cloudmade.xlogger:xlogger:1.1.0'
annotationProcessor 'com.cloudmade.xlogger:xlogger:1.1.0'

Звичайно, якщо ви використовуєте Kotlin, замініть annotationProcessor на kapt (і не забудьте apply plugin: ‘kotlin-kapt').

Використання

Якщо ви хочете логувати встановлення нового значення в ObservableField, ви повинні анотувати його @Loggable та викликати метод XLogger.init(), передаючи екземпляр класу як його аргумент.

public class ViewModelMainActivity {

   @Loggable
   public android.databinding.ObservableField<String> messageObservable = new android.databinding.ObservableField<>();

   public ViewModelMainActivity() {
       *.XLogger.init(this);
   }
}

Деталі реалізації

Під час компіляції AnnotationProcessor знаходить ObservableFields, анотовані @Loggable, та генерує клас з назвою «EnclosingClassSimpleName + Initializer» зі статичним методом initXLogger().

У статичному методі initXLogger() створюється новий відповідний екземпляр генерованої обгортки (ObservableInt -> ObservableIntWrapper, ObservableFloat -> ObservableFloatWrapper і т. д.) і встановлюється замість оригінального ObservableField. Ця обгортка розширює класс ObservableField і перевизначає метод set(), який фактично логує встановлення нового значення.

public static void initXLogger(ViewModelMainActivity enclosingClass) {
   *.generated.ObservableFieldWrapper<java.lang.String> newFieldMessageObservable = new *.generated.ObservableFieldWrapper(enclosingClass.messageObservable.get(), "messageObservable", enclosingClass.getClass().getSimpleName());
   enclosingClass.messageObservable = newFieldMessageObservable;
}

Щоб не викликати методи зі згенерованого класу в коді клієнта, ми створили XLoggerInitializerFactory, який створюється під час компіляції та XLogger.init(), що доступний перед компіляцією. XLoggerInitializerFactory виступає як міст між згенерованим «EnclosingClassSimpleName + Initializer» зі статичним методом initXLogger() і XLogger.init().

public class XLogger {
    public static void init(Object enclosingClass) {
       try {
           Class.forName("*.XLoggerInitializerFactory").getMethod("init", enclosingClass.getClass())
                   .invoke(null, enclosingClass);
       } catch (Exception e) {
           System.out.println(e.getMessage());
       }
    }
}

public class XLoggerInitializerFactory {
   public static void init(ViewModelMainActivity enclosingClass) {
       ViewModelMainActivityInitializer.initXLogger(enclosingClass);
   }
}

Після анотування ObservableField за допомогою @Loggable і виклику методу XLogger.init(), ви зможете побачити рядок в logcat після того, як встановите нове значення в нього.

com.cloudmade.xlogger D/UI: value Hello World! was set into ViewModelMainActivity.messageObservable

Наразі підтримуються ObservableFields:

  • ObservableBoolean
  • ObservableByte
  • ObservableChar
  • ObservableDouble
  • ObservableFloat
  • ObservableInt
  • ObservableLong
  • ObservableShort
  • ObservableField<T>

Висновок

Ви можете логувати встановлення значення в ObservableField у вашому застосунку, не змінюючи значною мірою початковий код. На GitHub є приклад застосунку та початковий код бібліотеки.


Цю статтю англійською мовою ви можете прочитати тут.

LinkedIn

1 комментарий

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

DataBinding підтримує LiveData, як на мене це набагато зручніше ніж всі ці Observable Fields

Подписаться на комментарии