일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 오픈소스
- Linux
- 명심보감
- DART
- Coroutine
- 소울칼리버6
- 공부집중
- kotlin
- ASMR
- 코틀린
- 파이썬
- bash
- androidx
- 좋은글필사하기
- 벤자민플랭클린
- 이모지메모
- Streaming
- Freesound
- 1인개발자
- 장자명언
- 공자명언
- recyclerview
- 이모지
- 명언모음
- Android
- Firebase
- jetpack compose
- FSM
- Flutter
- 넷플릭스
Archives
- Today
- Total
Vintage appMaker의 Tech Blog
[Flutter] Web App에서 javascript와 연동 본문
Source code or Tip/Flutter & Dart
[Flutter] Web App에서 javascript와 연동
VintageappMaker 2022. 11. 13. 11:40
Flutter 3.0으로 오면서 멀티플랫폼으로 Flutter는 안정적으로 변했다. 특히 Web app에서 PWA(Progressive Web App)을 만든다면 Flutter는 정말 괜찮은 선택 중에 하나이다. 그런데, Fluttrer로 Web App을 만들다보면 기존의 라이브러리들이 javascript로 되어있는 경우가 있는데, 이럴 때는 Javacript와 interface를 해야 한다.
1. javascript를 web 폴더에 작성한다. (app.js)
flutter 프로젝트의 web 폴더안의 index.html이 있는 곳에 원하는 자바스크립트를 작성하여 코딩을 한다.
[app.js]
window.state = {
reserved1: '전역변수처럼 사용가능'
}
// 호출예제
// 이 파일에서 apiTest와 같은 구조로
// WebPage에 전달해주면 된다.
function apiTest(jsonParam, onCallback) {
// 파라메터처리 {"id" : 숫자번호}
console.log(jsonParam);
var obj = JSON.parse(jsonParam);
console.log(obj);
// id라는 값이 넘어온다.
var num = obj.id;
var url = 'https://jsonplaceholder.typicode.com/posts/'+ num;
callServerTest(url, onCallback)
}
// 네트워크 api 호출
function callServerTest(url, onCallback) {
fetch(url)
.then(response => response.json())
.then(json => {
// 결과값 전달
var data = JSON.stringify(json, null, 4);
onCallback(data)
});
}
2. index.html을 수정한다.
flutter 프로젝트의 web 폴더안의 index.html을 위와 같이 수정한다.
3. flutter 소스에서 javascript를 호출한다.
import 'dart:js' as js;
를 한 후, js.context.callMethod()를 통해 javascrip 함수를 호출한다. app.js에서 정의한 함수를 호출하는데, 예제에는 결과물을 callback으로 받아처리하는 구조로
정의되어 있다.
4. 빌드한다.
flutter build web --release
5. 주의점
최종 릴리즈를 하려면 build한 web 폴더에 작성한 js 파일을 복사해주어야 한다.
그리고 js 파일을 수정한 것이 웹에서 적용되지 않았을 경우가 종종 발생하는데,
이 때에는 chrome에서 ctrl + shift + r을 통해 강력하게 갱신을 해야 한다.
6. 전체소스
[app.js 소스]는 위에 기술되어 있으므로 Flutter의 메인소스만 기술한다.
[main.dart]
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'dart:js' as js;
void main() {
runApp(PWATesterApp());
}
class PWATesterApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
scrollBehavior: DeskScrollBehavior(),
debugShowCheckedModeBanner: false,
title: 'PWA Javascript Interface',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MainPage(),
);
}
}
class MainPage extends StatefulWidget {
MainPage({Key? key}) : super(key: key);
@override
_MainPageState createState() => new _MainPageState();
}
class _MainPageState extends State<MainPage> {
TextEditingController ctrlTextFunction = TextEditingController();
TextEditingController ctrlTextParam = TextEditingController();
var resultText = "";
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Color(0xffaa2344),
width: double.infinity,
height: double.infinity,
padding: EdgeInsets.all(58.0),
child: Container(
child: SingleChildScrollView(
child: Column(
children: [...buildMainWidgets()],
),
),
),
));
}
// Main 화면
List buildMainWidgets() {
var inputColor = Colors.deepOrange;
var title = Text(
"Javascript Interface",
style: TextStyle(fontSize: 42, color: inputColor, decorationThickness: 3),
);
var inputText = TextField(
style: TextStyle(color: Colors.white),
controller: ctrlTextFunction,
decoration: InputDecoration(
suffixIcon: IconButton(
color: Colors.white,
onPressed: ctrlTextFunction.clear,
icon: Icon(Icons.clear),
),
enabledBorder:
OutlineInputBorder(borderSide: BorderSide(color: inputColor)),
focusedBorder:
OutlineInputBorder(borderSide: BorderSide(color: inputColor)),
labelText: '함수명',
hintText: "app.js에 정의한 함수명",
hintStyle: TextStyle(color: Colors.grey),
labelStyle: TextStyle(color: inputColor)));
var inputText2 = TextField(
style: TextStyle(color: Colors.grey),
controller: ctrlTextParam,
keyboardType: TextInputType.multiline,
maxLines: null,
decoration: InputDecoration(
suffixIcon: IconButton(
color: Colors.white,
onPressed: ctrlTextParam.clear,
icon: Icon(Icons.clear),
),
enabledBorder:
OutlineInputBorder(borderSide: BorderSide(color: inputColor)),
focusedBorder:
OutlineInputBorder(borderSide: BorderSide(color: inputColor)),
labelText: 'json 포멧 파라메터',
hintText: "예: {\"id\":1}",
hintStyle: TextStyle(color: Colors.white),
labelStyle: TextStyle(color: inputColor)));
var responseText = Container(
constraints: BoxConstraints(minWidth: 100, maxWidth: 500),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Text(
"$resultText",
style: TextStyle(color: Colors.yellowAccent),
),
),
);
return [
title,
Card(
elevation: 4.0,
color: Colors.transparent,
child: Container(
constraints: BoxConstraints(minWidth: 100, maxWidth: 500),
decoration: BoxDecoration(
color: Colors.amber, borderRadius: BorderRadius.circular(10.0)),
padding: EdgeInsets.all(15),
child: Column(
children: [
SizedBox(
height: 30,
),
inputText,
SizedBox(
height: 20,
),
inputText2,
SizedBox(
height: 20,
)
],
),
),
),
SizedBox(
height: 20,
),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.redAccent),
padding: MaterialStateProperty.all(EdgeInsets.all(20)),
),
onPressed: () {
callJavascriptAPI();
},
child: Text('전송하기'),
),
SizedBox(
height: 20,
),
responseText
];
}
// javascript 호출
void callJavascriptAPI() {
setState(() {
resultText = "";
});
js.context.callMethod('${ctrlTextFunction.text}', [
'${ctrlTextParam.text}',
(s) {
setState(() {
resultText = s;
});
}
]);
}
}
// 웹과 desktop에서 모바일처럼 터치 스크롤 지원하기 위함
class DeskScrollBehavior extends MaterialScrollBehavior {
@override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
};
}
'Source code or Tip > Flutter & Dart' 카테고리의 다른 글
[Flutter] 조건부 import (conditional import) (0) | 2022.11.19 |
---|---|
[Flutter] audioplayers를 이용한 mp3 플레이 (0) | 2022.11.14 |
[Flutter] Web app 배포시, 화면크기 고정 (0) | 2022.11.08 |
[Flutter] build Error 화면 커스텀하기 (0) | 2022.11.05 |
[중요에러] Incorrect use of ParentDataWidget Error in Flutter (0) | 2022.10.26 |
Comments