Как уменьшить размер базы мобильного приложения 1С на Android при работе с картинками?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке мобильных приложений на платформе 1С:Предприятие одной из самых частых проблем становится стремительный рост размера базы данных на мобильном устройстве. Особенно остро этот вопрос встает, когда в приложении реализован функционал фотографирования объектов или загрузки изображений товаров для офлайн-работы. Разработчики часто сталкиваются с тем, что даже после программной очистки реквизитов с типом ХранилищеЗначения физический размер файла базы данных на устройстве под управлением ОС Android не уменьшается, продолжая занимать гигабайты памяти и вызывая предупреждения системы о нехватке свободного места.

В этой статье мы подробно разберем внутренние механизмы СУБД мобильной платформы, выясним причины такого поведения системы и рассмотрим эффективные практические способы решения этой проблемы — как оперативные (сжатие существующей базы), так и стратегические (изменение архитектуры хранения файлов).

Почему размер базы данных не уменьшается автоматически после удаления данных?

Для начала проанализируем техническую сторону вопроса. Мобильная платформа 1С использует в качестве встроенной СУБД движок SQLite. Это легковесная и очень быстрая база данных, оптимизированная для работы на мобильных операционных системах. Однако у архитектуры хранения данных SQLite есть важная особенность, связанная с удалением записей.

Когда мы выполняем очистку реквизита объекта (например, присваиваем реквизиту с типом ХранилищеЗначения пустое значение Неопределено или удаляем элемент справочника целиком), физического удаления данных с диска не происходит. СУБД просто помечает страницы, на которых хранились эти данные, как «свободные» (так называемый список freelist) и планирует использовать их повторно при записи новых данных. С точки зрения операционной системы Android, файл базы данных сохраняет свой максимальный размер (например, 4 Гб), хотя фактически внутри него теперь может быть много пустого места.

Такой подход разработчиков SQLite обоснован следующими факторами:

  1. Производительность: Операция уменьшения физического размера файла на диске требует перезаписи и сдвига остальных данных. На мобильных устройствах это привело бы к сильным зависаниям интерфейса приложения.
  2. Ресурс накопителя: Постоянная перезапись больших объемов данных на флеш-памяти смартфона приводит к её ускоренному износу.

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

Решение 1: Запуск тестирования и исправления на мобильном устройстве

Рассмотрим штатный инструмент платформы 1С для физического сжатия базы данных. Начиная с версии мобильной платформы 8.3.9, разработчикам и администраторам доступно встроенное меню администрирования непосредственно на мобильном устройстве.

Разберем по шагам, как запустить процедуру сжатия таблиц:

  1. Откроем список мобильных приложений на устройстве (внутри сборщика или нативного лаунчера 1С).
  2. Нажмем на кнопку меню (троеточие или символ >) напротив нужного нам информационного приложения.
  3. В открывшемся контекстном меню выберем пункт «Администрирование».
  4. Перейдем в раздел «Тестирование и исправление».
  5. В списке доступных опций обязательно установим флаг напротив пункта «Сжатие таблиц информационной базы». Остальные проверки (проверка ссылочной целостности и т.д.) можно отключить для ускорения процесса.
  6. Нажмем кнопку запуска выполнения процедуры.

Во время этого процесса мобильная платформа выполняет команду VACUUM для базы данных SQLite. СУБД создает новый чистый файл базы, копирует туда только актуальные (заполненные) данные, после чего заменяет им старый раздутый файл. Физический размер приложения на диске уменьшится до фактического объема хранящейся информации.

Важное предупреждение: Для выполнения операции VACUUM на мобильном устройстве временно требуется свободное место, сопоставимое с текущим размером базы данных. Если база занимает 4 Гб, а свободного места на телефоне осталось всего 200 Мб, процедура завершится ошибкой из-за нехватки памяти. В таком случае придется прибегнуть к альтернативным методам.

Решение 2: Альтернативные способы очистки и сжатия

Если штатное тестирование на устройстве запустить не удается из-за нехватки свободного места, мы можем применить следующие методы:

  1. Полный сброс данных приложения. Самый простой способ вернуть память пользователю — зайти в настройки смартфона (раздел «Приложения» -> [Ваше мобильное приложение] -> «Хранилище/Память») и нажать кнопку «Очистить данные». Вся база будет удалена «с нуля», приложение вернется к исходному чистому состоянию. После этого пользователю потребуется выполнить первоначальную синхронизацию с центральной базой.
  2. Сжатие базы на стационарном ПК. Мы можем скопировать файл базы данных 1Cv8.1CD с мобильного устройства на компьютер (через USB-подключение или FTP-сервер). Затем открываем этот файл на компьютере с помощью утилиты проверки целостности chdbfl.exe (входит в стандартную поставку платформы 1С) либо загружаем его в Конфигуратор и запускаем полное тестирование и исправление с флагом сжатия таблиц. Сжатый файл возвращаем обратно на мобильное устройство. Данный метод отлично подходит для отладки разработчиком, но сложен для внедрения у конечных пользователей.

Решение 3: Архитектурный переход на хранение файлов вне базы данных

Постоянно запускать сжатие таблиц — это борьба с симптомами, а не с причиной. Хранение картинок высокого разрешения внутри СУБД мобильного приложения является серьезной ошибкой проектирования. Разберем, как кардинально перестроить архитектуру приложения.

Вместо помещения бинарных данных картинок в реквизиты базы данных (через ХранилищеЗначения), правильным подходом будет сохранение картинок в виде обычных файлов во внутренней памяти устройства. В самой базе данных мы будем хранить только текстовый путь к этим файлам.

Посмотрим на пример кода, реализующий сохранение картинки во внешнюю файловую систему:


// Получаем уникальное имя для файла картинки на диске смартфона
ИмяФайла = РабочийКаталогДанныхПользователя() + "img_" + Строка(НоменклатураСсылка.УникальныйИдентификатор()) + ".jpg";

// Предположим, что ОтветОтСервера содержит двоичные данные картинки
ДвоичныеДанныеКартинки = ОтветОтСервера; 
ДвоичныеДанныеКартинки.Записать(ИмяФайла);

// Записываем путь к файлу в текстовый реквизит справочника
ОбъектНоменклатуры = НоменклатураСсылка.ПолучитьОбъект();
ОбъектНоменклатуры.ПутьКФайлуКартинки = ИмяФайла;
ОбъектНоменклатуры.Записать();

При таком подходе процедура очистки данных становится мгновенной для операционной системы. Нам больше не нужно перезаписывать базу данных. Мы просто удаляем физический файл с диска устройства, используя стандартные методы платформы 1С:


// Процедура удаления файла картинки с диска
ОбъектНоменклатуры = НоменклатураСсылка.ПолучитьОбъект();
Если ЗначениеЗаполнено(ОбъектНоменклатуры.ПутьКФайлуКартинки) Тогда
    Попытка
        УдалитьФайлы(ОбъектНоменклатуры.ПутьКФайлуКартинки);
        // Очищаем путь в базе данных
        ОбъектНоменклатуры.ПутьКФайлуКартинки = "";
        ОбъектНоменклатуры.Записать();
    Исключение
        ЗаписьЖурналаРегистрации("Ошибка удаления файла", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
    КонецПопытки;
КонецЕсли;

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

Решение 4: Предварительное сжатие и уменьшение разрешения картинок

Часто мобильное приложение используется агентами или экспедиторами для фиксации состояния товаров, витрин или документов. Камеры современных телефонов создают снимки весом 4–10 Мб с разрешением более 4000х3000 пикселей. Такое качество избыточно для учетной системы 1С.

Рекомендуется программно уменьшать разрешение и качество картинок непосредственно перед сохранением на диске или в базе данных. Для этого используем специальный объект платформы ОбрабатываемаяКартинка.

Проанализируем пример оптимизации разрешения изображения перед записью:


// Создаем объект для обработки полученного снимка
ОбрабатываемоеИзображение = Новый ОбрабатываемаяКартинка(ИсходнаяКартинка);

// Задаем разумное ограничение по ширине и высоте (например, 1024x768 пикселей)
ОбрабатываемоеИзображение.УстановитьМаксимальныйРазмер(1024, 768);

// Получаем оптимизированную картинку в формате JPEG с качеством 70%
ОптимизированнаяКартинка = ОбрабатываемоеИзображение.ПолучитьКартинку(ФорматКартинки.JPEG, 70);

// Теперь получаем значительно уменьшенные двоичные данные
ДвоичныеДанныеДляСохранения = ОптимизированнаяКартинка.ПолучитьДвоичныеДанные();

Такое простое действие позволяет уменьшить размер каждой фотографии в 10–20 раз (с 5 Мб до 150-300 Кб). При этом визуальное качество на экранах смартфонов остается превосходным, текст на документах отлично читается, а база данных или папка приложения перестанут стремительно разрастаться.

Решение 5: Загрузка картинок по требованию (кэширование)

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

Рассмотрим оптимальный алгоритм динамического кэширования:

  1. При утренней синхронизации загружаем только текстовую информацию о товарах (наименование, код, цены, остатки).
  2. Когда пользователь открывает форму списка или карточку конкретного товара, проверяем наличие файла картинки в локальной папке устройства.
  3. Если файл отсутствует и есть интернет-соединение, отправляем фоновый запрос на центральный сервер 1С, скачиваем картинку, сохраняем её локально (кэшируем) и отображаем пользователю.
  4. Если интернета нет — отображаем заглушку «Нет изображения».
  5. Раз в неделю запускаем регламентную очистку локальной папки кэша, удаляя файлы, к которым не было обращений за последние несколько дней.

Сочетание архитектурного подхода (хранение файлов вне базы данных), предварительного сжатия картинок и периодического запуска сжатия SQLite позволит вашему мобильному приложению стабильно работать на любых устройствах Android без риска переполнения памяти.

← На главную