субота, 9 травня 2020 р.

Android бібліотеки для побудови графіків (діаграм)

Задались питанням «Як побудувати графік (діаграму) у Android програмі?». Для цього існує вже ряд розроблених бібліотек для Android Java розробників. З тих, що я знайшов, більш менш пристойними є: SciChart, AndroidCharts, AChartEngine, AndroidPlot, GraphView, MPAndroidChart. Останні дві є найбільш популярними. Існують також дуже простенькі невеличкі бібліотеки, які зосереджуються на малюванні одного якогось графіку, найчастіше лінійного.

SciChart – платна багатоплатформна бібліотека для WPF, iOS, Android, Xamarin. Розробники стверджують, що вони зосереджуються на швидкості і високопродуктивності їхньої бібліотеки. Дозволяє будувати доволі складні динамічні графіки. Наявний непоганий посібник (Tutorial) для Android розробників. Проте дана бібліотека є платна і коштує від 850 до 3000 доларів США на одного розробника в рік.
SciChart library, example, Android Graph, Plot
Приклад програми з використанням SciChart

четвер, 7 травня 2020 р.

FileChooser (FilePicker) in Android Program

Якщо необхідно реалізувати вибір файлів у вашій Android програмі, то додати до своєї програми так званий FileChooser або ж його ще називають FilePicker можна декількома способами. Можна використати стандартні засоби API Android, а можна скористатися сторонніми бібліотеками, яких зараз є доволі багато.

Передусім можна використати стандартний Intent.ACTION_GET_CONTENT. Для цього достатньо додати в обробник події натиснення кнопки наступні рядки:
Intent myFileIntent=new Intent(Intent.ACTION_GET_CONTENT);
myFileIntent.setType("*/*");
startActivityForResult(myFileIntent,10);
Також необхідно замістити (@Override) метод OnActivityResult і додати в ньому:
if (requestCode == 10 && resultCode == RESULT_OK) {
    String path=data.getData().getPath();
    textView.setText(path);
}
В результаті після натиснення кнопки з’явиться стандартна активність, яка дозволяє вибрати звідки вибирати файли і навіть, які засоби встановлені у системі використати. Наявні елементи можуть відрізнятися в залежності від конфігурації системи Android.

На моєму мобільному це виглядає так:
ACTION_GET_CONTENT, FileChooser Android
Інший варіант реалізувати вибір файлів є підключення сторонньої бібліотеки до Андроїда. Я опробував дві бібліотеки.

Material FilePicker ('com.nbsp:library:1.8') Детальніше тут.

Як її застосовувати також наведено на цьому відео:

Дана бібліотека дозволяє створити простий FileChooser в Android. Проте особисто мені сподобалась інша бібліотека, яка має більше можливостей щодо налаштувань, більше функцій та кращий зовнішній вигляд.

Це Android-FileBrowser-FilePicker ('com.adityak:browsemyfiles:1.9'). Детальніше тут.

Якщо необхідний FileChooser/FilePicker, то додаємо в gradle:
implementation 'com.adityak:browsemyfiles:1.9'
В обробник події кнопки для реалізації множинного вибору:
Intent i2 = new Intent(getApplicationContext(), FileChooser.class);
i2.putExtra(Constants.SELECTION_MODE, Constants.SELECTION_MODES.MULTIPLE_SELECTION.ordinal());
startActivityForResult(i2, PICK_FILE_REQUEST);
А у заміщеному (@Override) методі OnActivityResult додаємо:
if (requestCode == PICK_FILE_REQUEST && data!=null) {
      if (resultCode == RESULT_OK) {
          ArrayList selectedFiles  = data.getParcelableArrayListExtra(Constants.SELECTED_ITEMS);
      }
}
Результат тестування усіх трьох способі наведено на наступному відео:

Початковий код розміщено тут: https://github.com/volodimirg/TestFileChooser. Дивіться код MainActivity. У Manifest було додано лише дозвіл доступу до зовнішнього сховища даних.

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

Дивіться також:

субота, 2 травня 2020 р.

Як додати twitter card до блогу (blogger)

По замовчуванню коли твітнути статтю на платформі blogger, то в twitter з'являється не дуже привабливий tweet. Це можна виправити налаштувавши на нашому блозі twitter card (карточку твітера). 

Це можна зробити кількома способами. Спосіб один заходимо в налаштування блогу Тема/Редагувати html і додаємо такі рядки перед тегом </head> :

<meta content='summary_large_image' name='twitter:card'/>
<meta content='@your-name' name='twitter:site'/>
<meta content='@your-name' name='twitter:creator'/>

Інший спосіб надає більш розширенні можливості, зокрема можна вказали посилання на logo, яке буде з'являтися коли постити не пост, а головну сторінку, або сторінки блогу на blogger. Так же само додаємо наступний текст (взято тут):

<!--Twitter Card-->
<b:if cond='data:blog.pageType == "index"'> <!--homepage-->
    <meta name="twitter:card" content="summary" />
    <meta name="twitter:description" expr:content='data:blog.metaDescription' />
    <meta name="twitter:title" expr:content="data:blog.pageTitle" />
    <meta name="twitter:site" content="@username" />
    <meta name="twitter:image" content="YOUR_LOGO_URL" />
    <meta name="twitter:creator" content="@username" />
</b:if>
<b:if cond='data:blog.pageType == "static_page"'> <!--page-->
    <meta name="twitter:card" content="summary" />
    <meta name="twitter:description" expr:content='data:blog.metaDescription' />
    <meta name="twitter:title" expr:content="data:blog.pageTitle" />
    <meta name="twitter:site" content="@username" />
    <meta name="twitter:image" content="YOUR_LOGO_URL" />
    <meta name="twitter:creator" content="@username" />
</b:if>
<b:if cond='data:blog.pageType == "item"'> <!--blog post-->
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:description" expr:content='data:blog.metaDescription' />
    <meta name="twitter:title" expr:content="data:blog.pageName" />
    <meta name="twitter:site" content="@username" />
    <meta name="twitter:image" expr:content="data:blog.postImageUrl" />
    <meta name="twitter:creator" content="@username" />
</b:if>
<!--End Twitter Card-->
@username заміняємо на власний логін на твітері.
Переглянути результат можна використавши Twitter card validator.

Інколи не завжди з першого разу карточка нормально відображається в твітері і потребується повторний твіт. Або ж спочатку необхідно переглянути на валідаторі карточки, а згодом твітнути в твітері. Результат виглядає в моєму випадку так:

: twitter card

Клас EnumSet (Java)

EnumSet, Java, Collection, Колекції, Коллекции
Клас EnumSet — це одна з спеціалізованих реалізацій інтерфейсу Set для використання з перелічуваним типом даних (enum). EnumSet розширює AbstractSet та реалізує Cloneable та Serializable інтерфейси Java. EnumSet заміщує більшість методів інтерфейсів Set та Collection. EnumSet доволі швидка реалізація Set, швидша за HashSet, тому що всередині використовуються побітові операції, а не хеш-коди об’єктів.

EnumSet не синхронізований і повинен бути синхронізований ззовні, наприклад з використанням методу Collections.synchronizedSet(java.util.Set).

Всі елементи enum множини мають походити від єдиного перелічуваного типу, що вказується, коли множина створюється явно або неявно. EnumSet не дозволяє додавати значення null. Елементи зберігаються в порядку в якому їх подано в переліченні (enum).

EnumSet використовує безвідмовний (fail-safe) ітератор, що працює з копією EnumSet, тобто ітератор не буде викидати виняток ConcurrentModificationException, в разі зміни даних множини поза ітератором.

четвер, 30 квітня 2020 р.

Клас ArrayDeque (Java)

ArrayDeque, Java, Колекції, Коллекции
ArrayDeque (читається як еррейдек) – це клас який забезпечує двосторонню чергу. Іншими словами - це автоматично зростаючий масив, що дозволяє нам додавати або видаляти елементи з обох боків черги. ArrayDeque може бути використано як стек (LIFO, останній ввійшов - перший вийшов) або ж як черга (FIFO, перший ввійшов - перший вийшов).

ArrayDeque не може містити в якості елемента null.

Клас ArrayDeque швидший за клас Stack, якщо використовувати його в якості стеку і швидший за LinkedList, якщо використовувати в якості черги.

ArrayDeque розширює клас AbstractCollection та реалізує інтерфейси Deque, Cloneable, Serializable. Таким чином ми можемо використовувати для роботи з даним класом, як методи інтерфейсу Deque (який розширює інтерфейс Queue) так і методи інтерфейсу Collection.

Якщо використовується ітератор, то він буде викидати виняток ConcurrentModificationException, якщо вміст ArrayDeque був модифікований після створення ітератора. Таким чином ітератор необхідно з обережністю використовувати з ArrayDeque.

вівторок, 28 квітня 2020 р.

Як зберегти dataframe у csv файл (python)

save, dataframe, python, csv, зберегти, сохранить
CSV (від англ. comma-separated values 'значення, розділені комою', іноді character-separated values 'значення, розділені символом') — файловий формат для представлення табличних даних, у якому поля відокремлюються символом коми (або крапкою з комою) та переходу на новий рядок. Поля, що містять коми, декілька рядків, або лапки (позначаються подвійними лапками), мають обмежуватися з обох боків лапками. CSV формат простий та зручний для програмної обробки, тому його часто використовують для збереження різноманітнийх табличних даних з метою подальшої обробки їх різноманітними програмами. Практично усі сучасні мови, які займаються обробкою даних, мають зручні функції для читання даних у даному форматі.

Для збереження DataFrame у csv файл у Python використовується метод(функція) to_csv() класу pandas.DataFrame. Наприклад так:
import pandas as pd
df=pd.DataFrame({"Years": [1990, 1991, 1992, 1993, 1994, 1995, 1997],
    "Price1": [1, 5, 6, 10, 8, 9, 2],
    "Price2": [5, 6, 7, 8, 9, 15, 12],
    })
df.to_csv(r"C:\data\report_df.csv", index=False, sep=";")
r спереду адресу означає, що не потрібно враховувати службові символи у рядку шляху. Без r у windows шлях прийшлось би писати через дві косі риски, так:
df.to_csv("C:\\data\\report_df2.csv", index=False, sep=";")
Найбільш корисні аргументи методу to_csv наведено в таблиці.

Сценарій
Аргумент
Приклад
Змінити розділювач по замовчуванню
sep
df.to_csv(…, sep=';')
Записати без індексів
index
df.to_csv(…, index=False)
Записати без заголовків
header
df.to_csv(…, header=False)
Записати підмножину стовпчиків
columns
df.to_csv(…, columns=['x', 'y'])
Кодування формату файлу
encoding
df.to_csv(…, encodings='utf-8')
Стиснути   CSV
compression
df.to_csv(…, compression='gzip')
Задати формат часу
date_format
df.to_csv(…, date_format='%d/%m%Y')
Зберегти NaNs as "N/A"
na_rep
df.to_csv(…, na_rep='N/A')

понеділок, 27 квітня 2020 р.

Клас PriorityQueue (Java)

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

PriorityQueue має наступні конструктори: