Доброго времени суток. В данной статье рассматривается пример реализации ReactJS-компонента в мобильном приложении, разработанном на движке Unity 2017.4 LTS. Польза владения таким инструментом обусловлена тем, что на момент написания настоящей статьи ReactJS является самой популярной библиотекой для создания веб-компонентов, и таких компонентов уже написано превеликое множество. Так почему бы этим не воспользоваться? Можно просто вставить готовый веб-компонент, который визуально будет неотличим от компонента интерфейса, реализованного на движке. Кроме того, даже если Вы не нашли нужное, то очевидно, что верстать и добавлять интерактив с помощью HTML+CSS+JS гораздо проще и приятнее, чем в Unity. Конечно, придется реализовать взаимодействие веб-компонента и приложения, о чем будет рассказано в статье.

Начнем с почвы. Для того, чтобы встроить React-компонент в мобильное приложение нам нужны React-компонент и мобильное приложение. Исходный код React-компонента Вы можете найти по этой ссылке, а проект Unity с уже встроенным WebView - по этой. WebView в данном контексте - это специальная обертка над встроенным в устройство браузером для вывода веб-страниц внутри приложения. В своих проектах мы используем две различных кроссплатформенных реализации WebView: платную и бесплатную. В примере, естественно, используется бесплатная.

Итак, с одной стороны имеется инструмент, позволяющий выводить Веб-страницы в приложении, реагировать на событие загрузки страницы при помощи одного callback-метода, принимать и обрабатывать сообщения от браузера при помощи другого, а также выполнять JavaScript-код. С другой - обыкновенный Веб-компонент, скрипт для которого написан на ReactJS. Цель - подружить обе стороны.

В общем случае нет необходимости как-то менять Веб-компонент для отображения через WebView, поскольку WebView использует встроенный в устройство браузер. При такой постановке страница выведется как есть. Нас такой расклад не устроил по двум причинам: во-первых, мы разрабатываем мобильное приложение, во-вторых, хотелось бы при инициализации React-компонента сразу передать ему нужные данные.

Первое накладывает свой отпечаток на файле HTML-разметки, в котором рендерится компонент. А именно, в содержимое тега мы поместили следующую мета-информацию.

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="mobile-web-app-capable" content="yes">
  <meta name="theme-color" content="#000000">
  <meta name="description" content="React component for Unity-based mobile application">
  <title>React Component</title>
  <script>
    // Пример передачи данных из приложения
    window.initialData = {}; // Данные будут переданы из Unity
  </script>
</head>

Решение второй задачи, как можно видеть в предоставленном примере, заключается в том, что мы оборачиваем инициализацию ReactDOM.render() в функцию с параметром для данных, которую затем вызовем из приложения.

window.createAboutComponent = function (data) {
    ReactDOM.render(, document.getElementById('container'));
};

С обыкновенными React-компонентами разобрались. Далее мы хотели улучшить компонент, добавив возможность передавать сообщения приложению. В предложенной реализации Webview это осуществляется при помощи объекта window.Unity, который содержит функцию call, обеспечивающую передачу строки в callback-метод C#. Для удобства лучше вынести взаимодействие компонента с Unity в отдельный скрипт.

function createAPIObject(w) {
  const APIObject = {
 
    //Закрывает Webview в приложении
    close: function() {
      if(window.Unity) window.Unity.call("close");
    }
 
  };
 
  APIObject.close = APIObject.close.bind(APIObject);
 
  return APIObject;
}
 
let api;
 
//Инициализация объекта API
(function Init(w) {
  if(!w.unityApi) {
    api = createAPIObject(w);
    w.unityApi = api;
  } else {
    api = w.unityApi;
  }
})(window);
 
export default {
  close: api.close,
};

Теперь, добавляя в скрипт зависимость import unityApi from '../utils/unityApi';

разработчик получает доступ к функциям взаимодействия с Unity приложением.

Далее перейдем к нюансам в Unity. Есть две проблемы, причем, одна только с Android, другая со всеми, кроме Android. В Android, как известно, всё содержимое приложения есть Java-архив, из-за чего Unity приходится особым образом взаимодействовать с внутренними файлами, а именно при помощи класса www. Но, поскольку наш Веб-компонент поставляется как HTML файл с зависимостями, ссылки на нутро apk не работают. Проблему решает перенос таких файлов в persistentDataPath на время работы приложения. Пример реализации копирования файлов можно посмотреть в классе WebViewController, область Loading region.

В других системах, в том числе и в редакторе Unity, реализация WebView от Gree по каким-то причинам не инициализирует объект window.Unity. Исправим:

WebView.EvaluateJS(@"
	window.Unity = {
		call: function(msg) { 
		  var iframe = document.createElement('IFRAME'); 
		  iframe.setAttribute('src', 'unity:' + msg); 
		  document.documentElement.appendChild(iframe); 
		  iframe.parentNode.removeChild(iframe); 
		  iframe = null; 
	    } 
	};
");

Теперь callback Webview обрабатывает строку сообщения, переданную из браузера.

Осталось реализовать загрузку файла с Веб-компонентом и инициализировать его, передав нужные данные, что и сделано в методе WebViewController.LoadPage, который принимает в качестве параметров имя HTML-файла и строку JS кода для исполнения. В примере загружается страница характеристик товара и передается JSON-объект, представляющий данные для отображения. Важно отметить, что выполнение JS-кода необходимо осуществлять только после загрузки файла с компонентом и всех необходимых зависимостей. По этой причине переданная в обработчик WebView JS-строка сначала сохраняется в переменную и только по вызову callback-метода onLoad передается на исполнение.

На этом все. В заключение важно сказать, что созданные для мобильного приложения веб-компоненты обладают всеми преимуществами, которые предоставляет библиотека React, как, например, динамическая загрузка страницы и стилей. Богатая экосистема и компонентный подход позволяют многократно переиспользовать уже написанный код, не прибегая к существенным временным затратам. Кроме того, Facebook, как разработчик этой библиотеки, предоставляет отличные средства отладки React-компонентов в браузере, что в совокупе заметно ускоряет процесс создания конечного продукта в сравнении с другими известными JavaScript-фреймворками. По этим причинам React уже на протяжении более чем двух лет занимает позицию самой популярной библиотеки для Frontend-разработки и сохраняет такой статус к середине 2018 года.

Добавить комментарий