Статьи

Введение в Xamarin.Forms и SQLite

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

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

На данный момент, давайте предположим, что вы решили пойти по пути Xamarin.Forms, потому что вы заинтересованы в ориентации на несколько платформ не только в логике для вашего приложения, но и для уровня пользовательского интерфейса.

Отлично. Но что вы делаете сейчас, когда вам нужно хранить информацию в вашем приложении? Не волнуйтесь, есть очень простое решение этой проблемы, SQLite.

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

Мы не будем рассматривать все функции SQLite в этом руководстве просто потому, что их слишком много. Будьте уверены, что у вас будет возможность легко создавать структуру таблиц для хранения данных и извлечения их в вашем приложении. Это те концепции, на которых мы сосредоточимся в этом уроке.

В мире Xamarin.Forms SQLite естественным образом подходит по очень простой причине. Движок SQLite легко доступен на iOS и Android. Это означает, что вы можете использовать эту технологию прямо из коробки, когда вы решите написать приложение Xamarin.Forms.

Для получения доступа к функциональности SQLite в приложениях Windows Phone требуется еще один шаг, о котором мы поговорим чуть позже. Все эти функциональные возможности и кроссплатформенность доступны, но как мы получим доступ к реализации нативной платформы из нашего кода C # в Xamarin.Forms? Из хорошей упаковки NuGet, вот как. Давайте взглянем.

Давайте начнем с создания простого приложения Xamarin.Forms. В этом руководстве я буду использовать Mac с Xamarin Studio, но вы также можете легко использовать Xamarin Studio или Visual Studio, работающие на ПК.

Мы начинаем этот процесс с создания нового приложения Xamarin.Forms. Для этого просто выберите семейство шаблонов проектов мобильных приложений слева и выберите один из шаблонов Xamarin.Forms справа. Вы можете использовать либо PCL, либо Shared версию шаблона, но для этого случая я буду использовать PCL . Вы можете следовать одному из них, но будет небольшая разница, если вы выберете шаблон Shared позже.

Вы можете дать проекту любое имя, которое вам нравится. Я назову этот проект IntroToSQLite . После того, как вы нажмете кнопку OK , ваша среда IDE пройдет процесс создания решения. Ваше решение будет содержать четыре проекта:

  1. IntroToSQLite — проект PCL
  2. IntroToSQLite.Android — проект Android
  3. IntroToSQLite.iOS — iOS проект
  4. IntroToSQLite.WinPhone — проект Windows Phone (только на ПК)

Теперь, когда у нас настроена базовая структура проекта, мы можем начать добавлять доступ к SQLite в наш проект PCL. Нам нужно установить новый пакет в наш проект с именем SQLite.Net. Это оболочка .NET для SQLite, которая позволит нам получить доступ к встроенной функциональности SQLite из XLmarin.Forms PCL или Shared проекта.

Мы получаем доступ к этому пакету NuGet, щелкая правой кнопкой мыши на Пакеты или Ссылки , в зависимости от того, какую IDE вы используете, и выбирая Добавить пакет (или Ссылку ). В поле поиска введите sqlite.net . Это покажет вам довольно большую коллекцию пакетов, которые вы можете включить в свой проект.

Добавьте пакет SQLite NuGet

Поскольку я решил пойти по пути PCL для своего проекта Xamarin.Forms, мне нужно будет выбрать пакет SQLite.Net PCL для включения в мой проект. Какой из них вы выберете, если пошли по маршруту совместного проекта? Никто.

Если вы выбрали шаблон общего проекта ранее в этом руководстве, вам может быть интересно, как получить доступ к пакету SQLite. Короткий ответ: ты не можешь. Если вы помните из предыдущего урока , вы не можете добавить ссылки на общий проект. Чтобы получить доступ к SQLite из общего проекта, вы просто добавляете исходный код в проект.

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

Давайте начнем с определения интерфейса, который даст нам доступ к соединению с базой данных SQLite. В своем проекте PCL создайте новый интерфейс с именем ISQLite и замените реализацию следующим:

01
02
03
04
05
06
07
08
09
10
using System;
using SQLite.Net;
 
namespace IntroToSQLite
{
    public interface ISQLite
    {
        SQLiteConnection GetConnection();
    }
}

Это интерфейс, который мы реализуем и получаем доступ через DependencyService из собственных реализаций.

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
using System;
using SQLite.Net.Attributes;
 
namespace IntroToSQLite
{
    public class RandomThought
    {
        [PrimaryKey, AutoIncrement]
        public int ID { get;
        public string Thought { get;
        public DateTime CreatedOn { get;
 
        public RandomThought ()
        {
        }
    }
}

Как видите, это очень простой класс с тремя свойствами. Два из этих свойств — это обычные повседневные свойства, Thought и CreatedOn . Эти два свойства будут представлять столбцы в базе данных SQLite, которая будет содержать таблицу с именем RandomThought . Третье свойство, ID , также будет представлять столбец в таблице и содержать уникальный идентификатор, который мы можем использовать для ссылки на конкретную строку RandomThought в таблице.

Интересно, что свойство ID имеет два атрибута: PrimaryKey и AutoIncrement . PrimaryKey сообщает SQLite, что этот столбец будет первичным ключом таблицы, что означает, что по умолчанию он должен быть уникальным, и к нему применен индекс для ускорения извлечения из этой таблицы при обращении к строке этот столбец.

AutoIncrement означает, что когда мы вставляем новую RandomThought в эту таблицу, столбец ID будет автоматически заполняться следующим доступным целочисленным значением. Следующим шагом является создание этой таблицы в базе данных.

Мне нравится создавать класс, который представляет мою базу данных, и сохранять всю логику для доступа к базе данных и ее таблицам в этом классе. Для этого я создам класс с именем RandomThoughtDatabase :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using System;
using SQLite.Net;
using Xamarin.Forms;
using System.Collections.Generic;
using System.Linq;
 
namespace IntroToSQLite
{
    public class RandomThoughtDatabase
    {
        private SQLiteConnection _connection;
 
        public RandomThoughtDatabase ()
        {
            _connection = DependencyService.Get<ISQLite> ().GetConnection ();
            _connection.CreateTable<RandomThought> ();
        }
 
        public IEnumerable<RandomThought> GetThoughts() {
            return (from t in _connection.Table<RandomThought> ()
                    select t).ToList ();
        }
 
        public RandomThought GetThought(int id) {
            return _connection.Table<RandomThought> ().FirstOrDefault (t => t.ID == id);
        }
 
        public void DeleteThought(int id) {
            _connection.Delete<RandomThought> (id);
        }
 
        public void AddThought(string thought) {
            var newThought = new RandomThought {
                Thought = thought,
                CreatedOn = DateTime.Now
            };
 
            _connection.Insert (newThought);
        }
    }
}

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

Во-первых, мы используем класс DependencyService чтобы получить зарегистрированный класс, который реализует интерфейс ISQLite и вызвать его метод GetConnection .

Во-вторых, мы используем метод SQLiteConnection класса SQLiteConnection для создания таблицы с именем RandomThought . Этот метод создает таблицу, если она еще не существует, и корректно завершает работу, если она уже существует.

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

Большая часть кода, который мы используем для взаимодействия с базой данных, будет найдена в проекте PCL (или Shared). Но нам все еще нужно немного поработать в нативных реализациях, чтобы все работало правильно.

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

Прежде чем мы действительно сможем добавить какую-либо функциональность SQLite в проект iOS, нам нужно добавить в этот проект пакеты SQLite.Net PCL, а также пакеты SQLite.NET PCL — XamarinIOS Platform . Вы можете выполнить те же действия, что и на шаге 2 , и обязательно добавить оба проекта. После добавления этого пакета вы можете начать писать код SQLite в проекте iOS.

Давайте создадим реализацию интерфейса ISQLite для iOS. Начните с создания нового класса с именем SQLite_iOS .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.IO;
using SQLite;
using IntroToSQLite.iOS;
using Xamarin.Forms;
 
[assembly: Dependency(typeof(SQLite_iOS))]
 
namespace IntroToSQLite.iOS
{
    public class SQLite_iOS: ISQLite
    {
        public SQLite_iOS ()
        {
        }
 
        #region ISQLite implementation
 
        public SQLite.Net.SQLiteConnection GetConnection ()
        {
            var fileName = «RandomThought.db3»;
            var documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
            var libraryPath = Path.Combine (documentsPath, «..», «Library»);
            var path = Path.Combine (libraryPath, fileName);
 
            var platform = new SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS ();
            var connection = new SQLite.Net.SQLiteConnection (platform, path);
 
            return connection;
        }
 
        #endregion
    }
}

Мы получаем доступ к правильному местоположению для хранения файла базы данных, создаем новый объект SQLiteConnection и передаем его обратно в наш проект PCL (или Shared). Атрибут сборки в верхней части файла используется для идентификации этого класса как Dependency которую можно получить с помощью метода Get класса DependencyService .

Этот шаг очень похож на предыдущий. Разница лишь в том, что код немного изменится из-за того, что расположение файла базы данных будет другим. Вам все равно нужно будет добавить соответствующие пакеты в проект Android ( SQLite.Net PCL и SQLite.NET PCL — XamarinAndroid ), как вы делали это раньше. После этого вы можете добавить соответствующий код в новый класс с именем SQLite_Android .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.IO;
using Xamarin.Forms;
using IntroToSQLite.Android;
 
[assembly: Dependency(typeof(SQLite_Android))]
 
namespace IntroToSQLite.Android
{
    public class SQLite_Android: ISQLite
    {
        public SQLite_Android ()
        {
        }
 
        #region ISQLite implementation
 
        public SQLite.Net.SQLiteConnection GetConnection ()
        {
            var fileName = «RandomThought.db3»;
            var documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
            var path = Path.Combine (documentsPath, fileName);
 
            var platform = new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid ();
            var connection = new SQLite.Net.SQLiteConnection (platform, path);
 
            return connection;
        }
 
        #endregion
    }
}

Теперь у вас есть рабочая реализация интерфейса ISQLite с точки зрения вашего Android-приложения.

Поскольку я запускаю это приложение с Mac, я не буду создавать реализацию Windows Phone, но если вы захотите сделать это, вы можете.

Первый шаг — добавить поддержку в ваш проект Windows Phone для SQLite. Как упоминалось ранее, SQLite поставляется по умолчанию на iOS и Android. Это не относится к Windows Phone, но поддерживается. Чтобы установить его, вы можете следовать инструкциям на веб-сайте Xamarin .

После установки SQLite процесс добавления функциональности для Windows Phone будет практически таким же, за исключением того, что устанавливаемые пакеты — это SQLite.Net PCL и SQLite.Net PCL — платформа WindowsPhone 8. Установив эти пакеты, вы можете создать реализацию интерфейса ISQLite Windows Phone.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;
using System.IO;
using Xamarin.Forms;
using IntroToSQLite.WinPhone;
 
[assembly: Dependency(typeof(SQLite_WinPhone)]
 
namespace IntroToSQLite.WinPhone
{
    public class SQLite_WinPhone: ISQLite
    {
        public SQLite_WinPhone ()
        {
        }
 
        #region ISQLite implementation
 
        public SQLite.Net.SQLiteConnection GetConnection ()
        {
            var fileName = «RandomThought.db3»;
            var path = Path.Combine (ApplicationData.Current.LocalFolder.Path, fileName);
 
            var platform = new SQLite.Net.Platform.WindowsPhone8.SQLitePlatformWP8 ();
            var connection = new SQLite.Net.SQLiteConnection (platform, path);
 
            return connection;
        }
 
        #endregion
    }
}

Там у вас есть это. Теперь у вас есть все ваши нативные реализации. Пришло время дать этому приложению пользовательский интерфейс и перенести ваши данные в базу данных.

Поскольку это руководство хорошо разбирается в теме Xamarin.Forms, я предполагаю, что вы, по крайней мере, обладаете базовыми рабочими знаниями о Xamarin.Forms. Имея это в виду, я не буду вдаваться в подробности процесса создания пользовательского интерфейса. Если вам нужна дополнительная справочная информация о Xamarin.Forms, ознакомьтесь с моими другими учебниками по Xamarin.Forms по Tuts +.

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

Сначала мы сосредоточимся на создании первой страницы, которая будет содержать список объектов RandomThought . Начните с создания нового файла в проекте PCL (или Shared) и назовите его RandomThoughtsPage . Замените реализацию по умолчанию следующим:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
using Xamarin.Forms;
 
namespace IntroToSQLite
{
    public class RandomThoughtsPage: ContentPage {
        private RandomThoughtDatabase _database;
        private ListView _thoughtList;
 
        public RandomThoughtsPage (RandomThoughtDatabase database)
        {
            _database = database;
            Title = «Random Thoughts»;
            var thoughts = _database.GetThoughts ();
 
            _thoughtList = new ListView ();
            _thoughtList.ItemsSource = thoughts;
            _thoughtList.ItemTemplate = new DataTemplate (typeof(TextCell));
            _thoughtList.ItemTemplate.SetBinding (TextCell.TextProperty, «Thought»);
            _thoughtList.ItemTemplate.SetBinding (TextCell.DetailProperty, «CreatedOn»);
 
            var toolbarItem = new ToolbarItem {
                Name = «Add»,
                Command = new Command(() => Navigation.PushAsync(new ThoughtEntryPage(this, database)))
            };
 
            ToolbarItems.Add (toolbarItem);
 
            Content = _thoughtList;
        }
 
        public void Refresh() {
            _thoughtList.ItemsSource = _database.GetThoughts ();
        }
    }
}

Большая часть работы, выполненной в этом классе, находится в конструкторе. Конструктор позволяет нам передать экземпляр RandomThoughtsDatabase чтобы получить все сохраненные мысли. Мы устанавливаем свойство « Title страницы в «Случайные мысли», извлекаем все существующие мысли, создаем новый экземпляр ListView и создаем ToolbarItem , который позволит нам нажать кнопку, чтобы открыть страницу ввода. Мы этого еще не реализовали, но скоро будем.

Чтобы вывести наш новый RandomThoughtsPage на экран, нам нужно немного изменить файл App.cs. В этом файле измените метод GetMainPage чтобы он выглядел следующим образом:

1
2
3
4
5
6
public static Page GetMainPage ()
{
    var database = new RandomThoughtDatabase ();
 
    return new NavigationPage (new RandomThoughtsPage (database));
}

Метод GetMainPage теперь создает новый экземпляр нашего класса RandomThoughtDatabase и возвращает новый экземпляр RandomThoughtsPage . С этим изменением наши приложения для iOS и Android должны выглядеть примерно так:

Страница случайных мыслей для iOS
Страница случайных мыслей для Android

Теперь у нас есть страница списка для всех наших объектов RandomThought , но у нас нет возможности ввести новые. Для этого мы создадим еще одну страницу, аналогичную предыдущей. Создайте новый файл в своем проекте PCL (или Shared) и назовите его ThoughtEntryPage . Замените реализацию по умолчанию следующим:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System;
using Xamarin.Forms;
 
namespace IntroToSQLite
{
    public class ThoughtEntryPage: ContentPage {
        private RandomThoughtsPage _parent;
        private RandomThoughtDatabase _database;
 
        public ThoughtEntryPage ( RandomThoughtsPage parent, RandomThoughtDatabase database)
        {
            _parent = parent;
            _database = database;
            Title = «Enter a Thought»;
 
            var entry = new Entry ();
            var button = new Button {
                Text = «Add»
            };
 
            button.Clicked += async (object sender, EventArgs e) => {
                var thought = entry.Text;
 
                _database.AddThought(thought);
 
                await Navigation.PopAsync();
 
 
                _parent.Refresh();
            };
 
            Content = new StackLayout {
                Spacing = 20,
                Padding = new Thickness(20),
                Children = { entry, button },
            };
        }
    }
}

В этом классе вся работа выполняется внутри конструктора. Мы получаем ссылку на родительскую страницу RandomThoughtsPage , а также на базу данных. Остальное — базовый код настройки с объектом Entry для ввода текста и Button .

Когда пользователь нажимает Button , мы используем базу данных для добавления новой мысли, отклоняем страницу, возвращаемся на страницу списка и вызываем метод Refresh для обновления ListView . Как только все это будет установлено, мы можем запустить его, чтобы ввести некоторые значения.

Вот как это выглядит на iOS и Android, чтобы высказать некоторые ваши мысли:

Добавление мыслей на iOS
Добавление мыслей на Android

После того, как вы ввели несколько мыслей, ваш список будет выглядеть примерно так:

Перечисление мыслей на iOS
Перечисление мыслей на Android

Там у вас есть это. Теперь у вас есть возможность добавить функциональность базы данных в ваше приложение Xamarin.Forms, чтобы с легкостью хранить и получать любые данные.

Чтобы продолжить ваше обучение с помощью Xamarin.Forms и SQLite, я поставлю перед вами следующую задачу. Посмотрите, можете ли вы улучшить это приложение, чтобы разрешить удаление мыслей и обновить страницу списка аналогично странице ввода. Удачи и счастливого кодирования.