Introdução ao NativeScript

O que é NativeScript?

O NativeScript é como você cria aplicativos iOS e Android multi-plataforma, nativos sem visualizações da web. Use Angular, TypeScript ou JavaScript puro para obter verdadeiramente UI nativa e desempenho enquanto compartilha habilidades e código com a web. Obtenha 100% de acesso a API nativas via JavaScript e reutilize pacotes de NPM, CocoaPods e Gradle.

O que não é NativeScript?

  • Não é Cordova (Webview, DOM)
  • Não é um compilador Cross

Exemplo Android

let time = new android.text.format.Time()
time.set(1, 0, 2015)
console.log(time.format("%D"))

O Resultado será:

"01/01/2015"

Exemplo IOS

let alert = new UIAlertView()
alert.message = "Hello World!"
alert.addButtonWithTitle("Ok")
alert.show()

E o resultado é:

Mas como é que isso funciona?

NativeScript e JS VMs

  • NativeScript executa JavaScript com o JavaScript VM (Virtual Machine)
    • JavaScriptCore no IOS
    • V8 no Android

Sendo executado com V8

let time = new android.text.format.Time()
time.set(1, 0, 2015)
console.log(time.format("%D"))

Sendo executado com JavascriptCore

let alert = new UIAlertView()
alert.message = "Hello World!"
alert.addButtonWithTitle("Ok")
alert.show()

Utilizando as API's Nativas

  • NativeScript usa reflexão para construir uma lista de APIs disponíveis para cada plataforma.
  • Para um ótimo desempenho, este metadata é gerado previamente, e injetado no pacote do aplicativo em tempo de construção

Injetando API Nativa

  • V8/JavascriptCore tem API's para injetar nas variaveis globais

Invocando API's

let time = new android.text.format.Time()

  • V8 / JavaScriptCore tem retorno de chamada C++ para a função JS chamadas e acessos de propriedade.
  • O tempo de execução do NativeScript usa esses callbacks para traduzir as chamadas JS para chamadas nativas.
  • No iOS, você pode chamar diretamente as APIs Objective-C do C++.
  • No Android, o NativeScript usa o JNI do Android (Java Interface Nativa) para fazer a ponte de C ++ para Java. let time = new android.text.format.Time()
  • (1) O retorno de chamada da função V8 é executado.
  • (2) O tempo de execução do NativeScript usa seus metadados para saber que Time() significa que precisa instanciar um Objeto android.text.format.Time.
  • (3) O tempo de execução do NativeScript usa o JNI para instanciar um objeto android.text.format.Time e mantém uma referência a ele.
  • (4) O tempo de execução do NativeScript retorna um objeto JS que proxy o objeto JavaTime.
  • (5) Controle retorna para JS onde o objeto proxy é armazenado como uma variável de tempo local.
let time = new android.text.format.Time()
time.set(1, 0, 2015)
console.log(time.format("%D"))

Então você escreve apenas codigo nativo? NÃO

TNS Modules

  • Módulos fornecidos com NativeScript que oferecem funcionalidade crossplatform.
  • Há dezenas deles e são fáceis de escrever você mesmo.
  • Os módulos TNS seguem as convenções do node module (CommonJS).

TNS File Module

const fileSystemModule = require("file-system")
new fileSystemModule.File(path)

Basicamente isso, se tornara os trechos a seguir...

// ANDROID
new java.io.File(path)

// IOS
NSFileManager.defaultManager()
fileManager.createFileAtPathContentsAttributes(path)

Modulo HTTP

const http = require('http')
http.getJSON("https://api.meuservico.com")
.then(response => {
  // Resultado
})

Custom Modulos TNS

// device.ios.js
module.exports = {
  version: UIDevice.currentDevice().systemVersion
}

// device.android.js
module.exports = {
  version: android.os.Build.VERSION.RELEASE
}

Usando o Custom Modulo

const device = require('./device')
console.log(device.version)

Como inicio meu projeto?

  • (1) Instalar NativeScript globalmente
    • npm install -g nativescript
  • (2) Requesitos NativeScript CLI
    • JDK, Apache Ant, Android SDK
    • Xcode, Xcode CLI Tools, iOS SDK

Iniciando um novo Projeto

Depois que já instalou o NativeScript

  • tns create hello-world && cd hello-world

Executando no iOS

  • tns platform add ios && tns run ios --emulator

Executando no Android

  • tns platform add android && tns run android --emulator

Listagem de arquivos

- Hello-World (Pasta do seu projeto)
  - app
    - app.css <-- Estilo do app
    - app.js  <-- Ponto de inicialização
    - main-page.css
    - main-page.xml
    - main-page.js
    - node_modules <-- Modulos Node
      - ...
    - App_Resources <-- Icones, SplashScreen, Arquivos de configuração e etc
      - ...
    - Tns_Modules <-- Modulos do NativeScript
      - ...
  - platforms
    - android
    - ios

App.js

const application = require('application')
application.mainModule = 'main-page'
application.start()

Pages

  • Estruturas XML
  • Elementos (e.g. <page>, <Label>)
<Page>
  <Label text="Olá Pessoal ;)" />
</Page>

Data Binding

<Page loaded="load">
    <Label text="Olá Pessoal ;)" />
</Page>

exports.load = (args) => {
  args.object.bindingContext = {message: "Hello World!"}
} 

Data Binding Melhorado

const observableModule = require('data/observable')

exports.load = (args) => {
  let data = new observableModule.Observable()
  data.set("message", "Hello World")
  args.object.bindingContext = data
}

CSS

Label{
  color: red;
  font-size: 20;
  width: 200;
  margin: 20;
}


SURPREENDENTE, NÃO?