Логування 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 є приклад застосунку та початковий код бібліотеки.


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

Похожие статьи:
Для того, чтобы проверить навыки кандидата, на собеседовании ему часто дают тестовое задание (домой или прямо в офисе). Есть и другие...
Автоматизация. Как много в этом слове! Магия, трудности, потенциал, развитие... Если Вас не пугают данные трудности, а «время...
В январе вышла моя статья про типы машинного обучения и способы их применения для повседневных задач. Спасибо всем...
К смартфону Nexus P6 уже возникли вопросы после прохождения им теста на скручивание, показавшие, что его корпус...
Кластер Brave1 відновив грантову програму для українських defence tech компаній і стартапів. Про це DOU повідомили...
Яндекс.Метрика