По заявлениям разработчиков, в операциях записи и чтения Snappy превосходит по скорости SQLite:

Итак, начнём. Для начала необходимо добавить dependencies в build.gradle:
implementation 'com.snappydb:snappydb-lib:0.5.2'
implementation 'com.esotericsoftware.kryo:kryo:2.24.0'
Теперь начнём, непосредственно, работу с самой БД.
Для начала разберёмся, как SnappyDB работать с примитивными типами и массивами.
Для наглядности создадим небольшую разметку:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/filmNameTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="25sp" android:layout_centerInParent="true" android:layout_margin="8dp" /> <TextView android:id="@+id/filmBudgetTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textSize="25sp" android:layout_below="@+id/filmNameTextView" android:layout_margin="8dp" /> <TextView android:id="@+id/genreTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textSize="25sp" android:layout_below="@id/filmBudgetTextView" android:layout_margin="8dp" /> <TextView android:id="@+id/isAdult" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/genreTextView" android:textSize="25sp" android:layout_centerInParent="true" /> </RelativeLayout>
Допустим, что мы будим хранить в нашей БД данные о фильме
В MainActivity создадим метод PutValues:
private void putValues(String name, int budget, boolean isAdult, String[] genres) throws SnappydbException { DB snappyDB = DBFactory.open(this,"Film"); // создание БД с именем Film (для создания новой также используется метод open) snappyDB.put("Name", name); snappyDB.putInt("budget", budget); snappyDB.putBoolean("isAdult", isAdult); snappyDB.put("genres", genres); //кладём в БД данные в зависимости от типа }
Заметьте, что метод, в котором мы работаем со SnappyDB должен выбрасывать исключение SnappydbException.
Теперь напишем метод setValues для получения данных из БД и их вывода:
private void setValues(DB snappyDB) throws SnappydbException { TextView filmNameTextView = findViewById(R.id.filmNameTextView), filmBudgetTextView = findViewById(R.id.filmBudgetTextView), genresTextView = findViewById(R.id.genreTextView), isAdultTextView = findViewById(R.id.isAdult); //поля из созданной ранее разметки String name = snappyDB.get("Name"); int budget = snappyDB.getInt("budget"); boolean isAdult = snappyDB.getBoolean("isAdult"); String[] genres = snappyDB.getObjectArray("genres", String.class);//2 параметр = имя класса // метод get... в зависимости от типа данных filmNameTextView.setText(name); filmBudgetTextView.setText(String.valueOf(budget)); isAdultTextView.setText(String.valueOf(isAdult)); for(int i = 0;i < genres.length;i++) { genresTextView.setText(genresTextView.getText() + " " + genres[i]); } }
Вызовем созданные методы в onCreate (обязательно окружив их блоком try/catch):
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { putValues("Forrest Gump", 677000000,false, new String[] {"Drama","Melodrama"}); } catch (SnappydbException e) { e.printStackTrace(); } try { DB snappyDB = DBFactory.open(this, "Film"); setValues(snappyDB); } catch (SnappydbException e) { e.printStackTrace(); } }
Запускаем и видим, что всё работает исправно:

А теперь разберёмся, как работать с собственными классами и другими сложными типами.
Создадим класс Film с 3 полями:
public class Film { private String name; private int budget; private String[] genres; public Film() {} public Film(String name, int budget, String[] genres) { this.name = name; this.budget = budget; this.genres = genres; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getBudget() { return budget; } public void setBudget(int budget) { this.budget = budget; } public String[] getGenres() { return genres; } public void setGenres(String[] genres) { this.genres = genres; } }
Уберём вызовы методов setValues и putValues в onCreate. Создадим в нём новый объект класса Film и добавим его в БД:
Film film = new Film("Shawshank redemption",28000000, new String[] {"Drama"}); try { DB snappyDB = DBFactory.open(this, "NewFilmDB"); snappyDB.put("FilmObj",film); } catch (SnappydbException e) { e.printStackTrace(); }
Переработаем метод setValues:
private void setValues(DB snappyDB) throws SnappydbException { TextView filmNameTextView = findViewById(R.id.filmNameTextView), filmBudgetTextView = findViewById(R.id.filmBudgetTextView), genresTextView = findViewById(R.id.genreTextView); Film film = snappyDB.getObject("FilmObj", Film.class); String name = film.getName(); int budget = film.getBudget(); String[] genres = film.getGenres(); filmNameTextView.setText(name); filmBudgetTextView.setText(String.valueOf(budget)); for(int i = 0;i < genres.length;i++) { genresTextView.setText(genresTextView.getText() + " " + genres[i]); } }
Вновь вызовем setValues в onCreate:
try { DB snappyDB = DBFactory.open(this, "NewFilmDB"); setValues(snappyDB); } catch (SnappydbException e) { e.printStackTrace(); }
Запускаем и видим, что всё работает:

Теперь давайте рассмотрим ещё несколько интересных функций SnappyDB:
1) Возможность искать ключи по префиксу:
Film film1 = new Film("Green mile",60000000,new String[] {"Drama", "Fantasy"}), film2 = new Film("Gentlemen",22000000,new String[] {"Comedy", "Crime"}), film3 = new Film("In Bruges",15000000,new String[] {"Comedy", "Crime", "Thriller"}); try { DB snappyDB = DBFactory.open(this, "NewFilmDB"); snappyDB.put("FilmObj: Green Mile",film1); snappyDB.put("FilmObj: Gentlemen",film2); snappyDB.put("FilmObj: In Bruges",film3); String[] filmKeys = snappyDB.findKeys("FilmObj:"); //помещаем в массив filmKeys ключи с префиксом "FilmObj:" //если по одному ключу помещаются несколько значений, рассматривается последний добавленный for(int i = 0;i < filmKeys.length;i++) { Log.d("film_key: ", filmKeys[i] + "\n"); } Log.d("film_name: ", snappyDB.getObject(filmKeys[2],Film.class).getName() + "\n"); //выводим эл-т по ключу, взятому из массива filmKeys } catch (SnappydbException e) { e.printStackTrace(); }

Вывод в лог
2) Итерация по БД:
try { DB snappyDB = DBFactory.open(this, "NewFilmDB"); for (String[] batch : snappyDB.allKeysIterator().byBatch(1)) { //итераторы работают с пакетами ключей(batch), а не с самими ключами for (String key : batch) { Log.d("film",snappyDB.getObject(key,Film.class).getName()); } } } catch (SnappydbException e) { e.printStackTrace(); }
Без использования byBatch у вас будет только KeyIterator, который не реализует Iterator или Iterable, поэтому вы не можете использовать его в цикле.
byBatch (n) создает BatchIterable, который является Iterable и Iterator. По сути, он просто вызывает next (n) для KeyIterator, когда вы вызываете next () для него.
Но byBatch стоит использовать только при большом кол-ве данных. В ином случае стоит использовать findKeys/findKeysBetween.
3) Удаление элемента по ключу:
snappyDB.del("FilmObj: Gentlemen");

Элемент удалён
4) Закрытие и удаление БД:
snappyDB.close(); snappyDB.destroy();
5) Узнать, существует ли ключ в БД:
snappyDB.put("FilmObj: Gentlemen",new Film()); boolean isExist = snappyDB.exists("FilmObj: Gentlemen");// true snappyDB.del("FilmObj: Gentlemen"); isExist = snappyDB.exists("FilmObj: Gentlemen");//false
Ну вот и всё. Вам решать, использовать ли эту БД в своих проектах. Она достаточно быстра и проста в использовании, но выбор за вами. Это далеко не единственная БД для Android.
P.S: SnappyDB на GitHub (оф.документация там же).
Различия между SQL и NoSQL: 1, 2
ссылка на оригинал статьи https://habr.com/ru/post/497222/
Добавить комментарий