Android studio создание таблицы kotlin

TableLayout и TableRow

Разметка TableLayout (Табличная разметка) позиционирует свои дочерние элементы в строки и столбцы, как это привыкли делать веб-мастера в теге table. TableLayout не отображает линии обрамления для их строк, столбцов или ячеек. TableLayout может иметь строки с разным количеством ячеек. При формировании разметки таблицы некоторые ячейки при необходимости можно оставлять пустыми. При создании разметки для строк используются объекты TableRow, которые являются дочерними классами TableLayout (каждый TableRow определяет единственную строку в таблице). Строка может не иметь ячеек или иметь одну и более ячеек, которые являются контейнерами для других объектов. В ячейку допускается вкладывать другой TableLayout или LinearLayout.

TableLayout удобно использовать, например, при создании логических игр типа Судоку, Крестики-Нолики и т.п.

Вот несколько правил для TableLayout. Во-первых, ширина каждой колонки определяется по наиболее широкому содержимому в колонке. Дочерние элементы используют в атрибутах значение match_parent. Атрибут TableRow для layout_height всегда wrap_content. Ячейки могут объединять колонки, но не ряды. Достигается слияние колонок через атрибут layout_span.

Если атрибуту android:stretchColumns компонента TableLayout присвоить значение «*», то содержимое каждого компонента TableRow может растягиваться на всю ширину макета.

Создаем таблицу прогноза погоды

Например, для создания таблицы прогноза погоды можно использовать следующий дизайн:

  • В первом ряду показать заголовок таблицы
  • Во втором ряду показать даты по типу календаря
  • В третьем ряду показать наибольшую температуру
  • В четвёртом ряду показать наименьшую температуру
  • В пятом ряду показать графику (дождь, снег, облачность, солнце)

Показать код (щелкните мышкой)

В альбомной ориентации наша разметка будет выглядеть следующим образом

Программное создание TableLayout

Усадка, усушка, утруска

Если текст в ячейке таблицы слишком длинный, то он может растянуть ячейку таким образом, что часть текста просто выйдет за пределы видимости. Чтобы избежать данной проблемы, у контейнтера TableLayout есть атрибут android:shrinkColumns. Мы рассмотрим программное применение данного атрибута через метод setColumnShrinkable().

Для начала смоделируем ситуацию и поместим в одну из ячеек очень длинный текст, который не поместится на экран:

Теперь напишем код для усадки текста:

Книжная полка

Создадим подобие книжной полки. Нам понадобится изображение одной полки, которая послужит фоном и изображение книги (найдите сами).

Объявим две константы, которые отвечают за количество полок и количество книг на каждой полке.

Откуда на верхней полке появился кот и как он туда забрался я не знаю. Вы уж сами разберитесь с ним.

Источник

База данных на SharedPreferences — Android Kotlin

Статья написана об учебном проекте, повторять такое на проде нельзя, как минимум это небезопасно. Намеренно используется не самая лучшая реализация тех или иных вещей, чтобы можно было подискутировать в комментариях.

Зачем всё это? Зачем?

Наверное, в вашей голове возник вопрос: «В каких ситуациях может понадобиться использование SharedPreferences, если абсолютно всё можно хранить в Базе Данных?»

Отвечаю: и правда, абсолютно всю информацию можно хранить в таком виде. Иметь таблицу с настройками приложения (например, тёмная тема: вкл/выкл), а в другой таблице хранить ту самую информацию, которую отображает само приложение. Но эффективно ли это? Если информации много и SQL запросы помогают вам, то да, но не стоит забывать, что Базы Данных в большинстве случаев являются сложным механизмом, из-за чего производительность вашего приложения может быть снижена. Если информации не так много, то гораздо выгоднее использовать SharedPreferences.

Краткая теория, как использовать SharedPreferences

Чтобы получить экземпляр класса SharedPreferences, в коде приложения используются два метода:

  • getPreferences() — внутри активности, чтобы обратиться к определённому для активности предпочтению,
  • getSharedPreferences() — внутри активности, чтобы обратиться к предпочтению на уровне приложения.

Все эти методы возвращают экземпляр класса SharedPreferences, из которого можно получить информацию с помощью ряда методов:

  • getBoolean(String key, boolean defValue) ,
  • getFloat(String key, float defValue) ,
  • getInt(String key, int defValue) ,
  • getLong(String key, long defValue) ,
  • getString(String key, String defValue) .

По умолчанию используется MODE_PRIVATE — только приложение имеет доступ к настройкам:

  • MODE_APPEND — присоединяет новые настройки к существующим,
  • MODE_ENABLE_WRITE_AHEAD_LOGGING ,
  • MODE_MULTI_PROCESS ,
  • MODE_WORLD_READABLE — позволяет другим приложениям читать настройки,
  • MODE_WORLD_WRITEABLE — позволяет другим приложениям записывать новые настройки.
Читайте также:  Живой обой iphone для андроид

Эти файлы настроек хранятся в каталоге: /data/data/имя_пакета/shared_prefs/имя.xml .

Начинаем эксперимент

Представим такой проект: на вход поступает json файл, в нём хранится информация о валютах (имя, стоимость и т. д.). Нам необходимо сохранить эти данные и при перезапуске приложения показать их, не читая json (все данные взяты из нашей БД). Возможные взаимодействия с карточкой валюты: изменение любого поля.

Все исходники вы сможете найти на GitHub в конце статьи.

Создадим самый обыкновенный класс и передадим ему в аргументы context для SharedPreferences. (Хотел бы услышать ваше мнение по поводу классов. Какой класс вы бы предпочли использовать в данной ситуации?)

Мы создадим два пространства. Первое будет хранить информацию о нашей DB и будет статично по своей размерности. В нём будет храниться количество наших карточек с валютами. Второе поле должно хранить те самые карточки, а значит — уметь динамически изменять свой размер.
Как оно будет работать? SharedPreferences хранит данные, как, грубо говоря, Map (ключ->значение), и вся информация находится в «таблице данных». Благодаря имени данной таблицы мы и будем передвигаться по карточкам. Новое имя таблицы = новая карточка. Таблицы мы будем называть цифрами, они будут выполнять роль их id. Так будет намного проще передвигаться по ним.

Создадим и проинициализируем глобальные переменные класса:

А вот и первая наша функция. Она позволяет узнать размер 2 поля (сколько таблиц оно содержит):

Если поле не создано, то возвращается 0.

Геттер создали, теперь время сеттера. Для этого создадим две функции:

ВНИМАНИЕ: если в конце не написать .apply(), изменения не сохранятся!

Вторая область

Теперь перейдём ко 2 области, нам необходимо уметь перемещаться по нашим «таблицам», для этого реализуем такую функцию:

Стоит немножко объяснить код. В аргументах мы принимаем название таблицы (её порядковый номер), после чего можно заметить проверку, которая сравнивает текущий порядковый номер таблицы с полученным, в случае если они не равны, происходит переприсвоение текущего названия таблицы и её открытие. Доступ к чтению таблицы мы получаем благодаря глобальной переменной prefs, а к редактированию — editor.

Добавление карточек к БД

Что же, думаю, можно перейти к заполнению нашей таблицы:

На вход мы получаем JSON объект, после чего увеличиваем количество всех наших таблиц, открываем новую таблицу и используем сеттеры. Ниже представлен код одного из таких сеттеров:

Тут без объяснений не обойтись. Функция принимает 2 аргумента, причём последний аргумент является необязательным (если его не изменять, он по умолчанию будет равен -1), а также может хранить null . Дальше идёт конструкция _id?.let<> , она позволяет запустить фрагмент кода (в фигурных скобках), если переменная не равна null . После чего идёт проверка, стандартное ли значение 2 аргумента. Если на вход мы получили номер таблицы -> открыть нужную таблицу. В конце присваиваем новое значение по ключу «ID» и не забываем применить все изменения с помощью .apply() . Для чего мы добавили возможность переменной _id хранить null , объясню чуть позже.

Подобные сеттеры нужно создать для каждого ключа JSON объекта.

Чтение карточки

Сеттеры отдельных ключей есть, а это значит, что наша самодельная БД уже умеет сохранять информацию, осталось научить её считывать. Ниже приведён пример одного из геттеров:

Мы можем наблюдать, как функция может принимать пользовательское имя таблицы, так и использовать значение по умолчанию. Если пользователь не вводил имя таблицы, то информация будет взята из текущей.

Поиск карточки

Замечательно, наша БД на SharedPreferences умеет сохранять и выводить данные, правда осталась одна нерешённая проблема. Предположим, что при работе с приложением пользователь захочет изменить определённую карточку, нажав на неё, для этого у нас уже существуют сеттеры, но откуда нам знать, какую именно таблицу нужно открыть для работы? Предположим, у нас есть возможность получить какую-нибудь информацию с карточки, например, сокращённое имя валюты. Получается, нам необходимо пройтись по всем существующим таблицам, найти совпадение и вывести название данной таблицы. Это долгая операция, поэтому таких ситуаций лучше не создавать, например, пусть каждая карточка в интерфейсе будет хранить свой локальный номер, который будет совпадать с названием таблицы, но если такой возможности нет, то в бой идёт наша новая «тяжёлая» функция:

В случае если совпадений не найдено, будет возвращено null. Поскольку данная функция, скорее всего, будет использована в комбинации с сеттерами и геттерами, мы и добавили в них поддержку null. Данная функция ищет совпадения по NumCode значению, и нам ничто не мешает сделать аналогичные функции для оставшихся ключей.

DataBase на SharedPreferences в действии

Перейдём в наш MainActivity и создадим экземпляр нашего класса, наименовав его db. После чего получим JSONobject из памяти Android и в функции «createDB» запишем всю интересующую нас информацию в нашу db, затем прочитаем некоторую информацию карточки в функции readInfoDB, выпишем её, следом изменим внутри лежащую информацию с помощью функции editInfoDB и снова распечатаем результаты:

Читайте также:  Не могу удалить камеру андроид

Поздравляю, оно работает! (P.S. lateinit в Kotlin советуют не использовать)

Если вдруг Logcat не работает, попробуйте его перезагрузить. (Обычно такое происходит из-за нехватки мощности компьютера).

Какие могут возникнуть трудности в будущем?

  • Удаление карточки-таблицы, т.к. это не связный список, при удалении все элементы будут сдвигаться, а это, в свою очередь, долгий процесс.
  • Добавление карточки не в конец списка приведёт к сдвигу всех элементов.
  • Нельзя наглядно увидеть, что хранится в Базе Данных.
  • При стирании кэша приложения всё сотрётся.
  • При замене всех параметров таблицы есть вероятность её потерять, т.к. неизвестно, по каким параметрам искать таблицу.
  • Очень рискованно.

Это был весёлый и интересный эксперимент, который и правда сработал. Можно ли это использовать на проде? Конечно же, нет, напомню, что это учебный проект и такой способ хранения информации небезопасен, но, надеюсь, эта статья показала вам, что при должном желании возможно абсолютно всё. В этом и есть прелесть программирования, ты можешь реализовать одну и ту же вещь разными способами. Если эта тема кажется вам интересной, дайте знать, сделаю 2 часть, где мы добавим много действительно крутых функций от старших братьев и полностью перепишем нашу DataBase. Например, используем шифрование, связной список и дадим возможность создавать пользовательские пространства. Обещаю, будет безумно интересно. Не забывайте делиться своим мнением о данной задумке и статье в принципе.

Если у вас есть замечания по коду — пишите, обсудим в комментариях.

Источник

Русские Блоги

Android Room By Kotlin

Введение в демо

Эта демонстрация представляет собой простое приложение, демонстрирующее использование синтаксиса Room в Kotlin.

Введение в комнату

Библиотека сохраняемости Room предоставляет уровень абстракции на основе SQLite, позволяя пользователям в полной мере использовать мощные функции SQLite, пользуясь более надежным механизмом доступа к базе данных.

Эта библиотека помогает вам создать локальную базу данных на устройстве, на котором запущено приложение.

1. Создайте пустой проект.

2. Обновите файл Gradle.

Библиотеку компонентов необходимо добавить в файл Gradle
в вашем build.gradle Внесите следующие изменения в (Модуль: приложение):
Примените его, добавив плагин Kotlin для обработки аннотаций kapt к другим плагинам, определенным в верхней части файла (Module: app).
bulid.gradle

В коде dependencies Добавьте следующий код в конец блока.

ПозжеПроект build.gradle (Project)

Здесь вы также можете перейти на официальный сайт, чтобы найти номер последней версииссылка на сайт

3. Создайте объект

Room позволяет создавать таблицы через Entity. Начнем сейчас.

Проанализируйте значение аннотации @ в следующем коде

  • @Entity(tableName = «todo_database»)
    каждый @Entity Класс представляет собой таблицу SQLite. Аннотируйте свой класс, чтобы показать, что это класс сущности. Если вы хотите, чтобы имя таблицы отличалось от имени класса, вы можете указать имя таблицы. Эта таблица называется «todo_database»
  • @PrimaryKey
    Каждой сущности нужен первичный ключ. Используйте здесь autoGenerate = true Для автоматического создания
  • @ColumnInfo(name = «todo_title»)
    Если вы хотите, чтобы имя столбца в таблице отличалось от имени переменной-члена, укажите это имя. Это назовет столбец «todo_title».

4. Создайте Дао

Что такое Дао?

В DAO (объект доступа к данным) укажите запросы SQL и свяжите их с вызовами методов. Компилятор проверяет SQL и генерирует запросы @Insert для общих запросов (например) из удобных комментариев. Room использует DAO для создания чистого API для вашего кода.

DAO должен быть интерфейсом или абстрактным классом.

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

В Room есть поддержка сопрограмм, что позволяет аннотировать ваши запросы с помощью модификатора приостановки, а затем вызывать их из сопрограммы или другой приостановленной функции.

Написать Дао

Давайте напишем DAO, который предоставляет следующий запрос:

  1. Расположите все заголовки в алфавитном порядке
  2. Вставить Todo
  3. Удалить все Todo
  1. TodoDao Интерфейс; Дао должен быть интерфейсом или абстрактным классом.
  2. В @Dao В аннотации указано, что это класс комнаты Дао.
  3. suspend fun insert(todo: Todo) Объявите функцию паузы для вставки Todo.
  4. Аннотация @Insert — это специальная аннотация метода DAO, вам не нужно предоставлять какой-либо SQL! (Существуют также аннотации @Delete и @Update для удаления и обновления строк, но они не используются в этом приложении.)
  5. onConflict = OnConflictStrategy.IGNORE Если Todo, выбранный в политике конфликтов, в точности совпадает с существующим Todo в списке, слово будет проигнорировано.
  6. suspend fun deleteAll() Объявите функцию паузы для удаления всех Todos.
  • на @Query Использование слишком много и разное, пожалуйста, проверьте информацию самостоятельно

5. Класс LiveData

При изменении данных обычно требуются некоторые меры, например отображение обновленных данных в пользовательском интерфейсе. Это означает, что вы должны наблюдать за данными, чтобы вы могли реагировать на их изменение.

В зависимости от того, как хранятся данные, это может быть сложно. Наблюдение за изменениями данных между несколькими компонентами приложения может создать четкий и строгий путь зависимости между компонентами. Это очень затрудняет тестирование и отладку.

Читайте также:  Перенаправление маршрутов android vpn

LiveData, класс библиотеки жизненного цикла для наблюдения за данными, может решить эту проблему. LiveData использует возвращаемое значение типа в описании метода, а затем Room генерирует все необходимые коды для обновления базы данных LiveData.
отражен в приведенном выше блоке кода следующим образом

Позже в этой демонстрации изменения данных будут отслеживаться через Observer.

7, добавьте RoomDatabase

Что такое RoomDatabase?

  • Комната — это уровень базы данных поверх базы данных SQLite.
  • Room отвечает за выполнение общих задач, которые ранее выполнялись NET.
  • Room использует DAO для отправки запросов к своей базе данных.
  • По умолчанию, чтобы избежать снижения производительности пользовательского интерфейса, Room не позволяет выполнять запросы в основном потоке. Когда запрос Room возвращает LiveData, запрос будет автоматически выполняться асинхронно в фоновом потоке.
  • Room обеспечивает проверку операторов SQLite во время компиляции.

Написать RomDatabase

Класс RoomDatabase должен быть абстрактным и может расширять RoomDatabase. Обычно для всего приложения требуется только один экземпляр базы данных Room.

Давайте сделаем это сейчас. Создайте файл класса Kotlin с именем WordRoomDatabase и добавьте следующий код:

Взглянем на код:

  • Room Класс базы данных должен быть abstract И расширить RoomDatabase
  • Вы используете класс аннотации в качестве базы данных Room, @Database И используйте параметр комментария, чтобы объявить сущность, принадлежащую базе данных, и установить номер версии. Каждой сущности соответствует таблица, которая будет создана в базе данных. Миграция базы данных выходит за рамки этой лаборатории кода, поэтому exportSchema Установить здесь как false Чтобы избежать генерации предупреждений. В реальном приложении вам следует рассмотреть возможность создания каталога для Room для экспорта архитектуры, чтобы текущую архитектуру можно было проверить в системе контроля версий.
  • Вы переходите за каждый @Dao Создайте абстрактный метод «получения», чтобы база данных предоставляла свой DAO.
  • Мы определили singleton , TodoRoomDatabase Чтобы предотвратить одновременное открытие нескольких экземпляров базы данных.
  • getDatabase Вернуться к синглтону. Он будет использовать построитель базы данных Room при первом доступе к базе данных. RoomDatabase Создайте объект в контексте приложения класса TodoRoomDatabase И назовите его для создания базы данных «todo_database».

8. Создать репозиторий

Что такое репозиторий?

Класс репозитория абстрагирует доступ к нескольким источникам данных. Репозиторий не является частью библиотеки архитектурных компонентов, но является рекомендуемым разделением кода и передовыми методами архитектуры. Класс Repository предоставляет чистый API для доступа к данным остальной части приложения.

Написать репозиторий

Создайте файл класса Kotlin с именем TodoRepository И вставьте в него следующий код:

  1. DAO передается конструктору репозитория, а не всей базе данных. Это потому, что ему нужен только доступ к DAO, потому что DAO содержит все методы чтения / записи базы данных. Нет необходимости предоставлять всю базу данных в репозиторий.
  2. Todo Список является государственной собственностью. по LiveData Из Room Получите список слов для инициализации; причина, по которой мы можем это сделать, заключается в том, что мы определили getAlphabetizedTodoList возвращение LiveData Методы. Room Все запросы выполняются в отдельных потоках. Потом, когда LiveData Когда данные изменились, observed Наблюдатель будет уведомлен в основном потоке.
  3. В suspend Модификатор сообщает компилятору, что это нужно вызывать из сопрограммы или другой функции паузы.

9. Создайте ViewModel.

Что такое VIewModel?

ViewModel Роль заключается в предоставлении пользовательского интерфейса данных и сохранении изменений конфигурации. ViewModel Выступает в качестве коммуникационного центра между репозиторием и пользовательским интерфейсом. Вы также можете использовать ViewModel Делитесь данными между клипами. ViewModel Это часть библиотеки жизненного цикла.

Зачем использовать ViewModel

ViewModel Сохраняйте данные пользовательского интерфейса приложения с учетом жизненного цикла, чтобы сохранить изменения конфигурации. Данные пользовательского интерфейса приложения Activity Класс и Fragment Разделите классы, чтобы лучше следовать принципу единой ответственности: ваши действия и фрагменты отвечают за вывод данных на экран, а вы ViewModel Может отвечать за сохранение и обработку всех данных, требуемых пользовательским интерфейсом.
в ViewModel , LiveData Используется для переменных данных, которые будет использовать или отображать пользовательский интерфейс. Использование LiveData дает несколько преимуществ:

  1. Вы можете поставить наблюдателей на данные (вместо опроса на предмет изменений) и только
    Обновляйте пользовательский интерфейс только при фактическом изменении данных.
  2. Библиотека ресурсов и пользовательский интерфейс полностью разделены.
  3. Нет обращений к базе данных от ViewModel (Все это обрабатывается в репозитории), чтобы сделать код более тестируемым.

viewModelScope

В Котлине все сопрограммы запускаются внутри CoroutineScope . Осциллограф контролирует жизненный цикл сопрограммы через ее работу. При отмене операции области консолидации будут отменены все сопрограммы, запущенные в области консолидации.

AndroidX lifecycle-viewmodel-ktx Библиотека добавлена viewModelScope Функция расширения класса ViewModel Чтобы вы могли использовать диапазон.

Реализовать ViewModel

Создайте для этого файл класса Kotlin и добавьте следующий код:

10. Наконец

Теперь нам нужно только вызвать метод вставки во ViewModel для вставки данных.

Конкретный код тестового интерфейса (RecyclerView и т. Д.) Показан по ссылке Github ниже.

Источник

Оцените статью