Vintage appMaker의 Tech Blog

[Flutter] 조건부 import (conditional import) 본문

Source code or Tip/Flutter & Dart

[Flutter] 조건부 import (conditional import)

VintageappMaker 2022. 11. 19. 18:59

window용 예제
web용 예제

Flutter로 개발을 하다보면 web app에서 사용했던 html 패키지를 가지고 Android 나 다른 플랫폼에서 빌드를 할 수 없을 때가 있다(HTML 패키지를 OS에 적용할 수 없다는 메시지와 함께 빌드에러가 발생한다). 주로 javascript 관련된 플러그인을 사용했을 때이다. 그럴 때는 조건부 import를 해서 소스를 이원화 해야 한다

 

1. web소스와 다른 플랫폼 소스를 파일수준으로 분리한다. 
2. 메인이 되는 소스에서 import시 [dart.library.html]를 채크한다.
3. dart.library.html인 경우는 웹이므로 웹을 import 한다.
4. import되는 각 소스에서 클래스형 또는 함수형은 동일하게 한다.

 

아쉬운 점이 있다면 C/C++처럼 조건부 컴파일이 아니라서 소스단위로 처리해야 한다. 

 

[main.dart]

import 'package:flutter/material.dart';
import 'package:testall/mobileUtil.dart'
    if (dart.library.html) 'package:testall/webUtil.dart';

void main() {
  runApp(PWATesterApp());
}

class PWATesterApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'conditional import',
      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 ctrlTextParam = TextEditingController();

  @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(
      "conditional import",
      style: TextStyle(fontSize: 42, color: inputColor, decorationThickness: 3),
    );

    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: '메시지',
            hintText: "메시지를 입력하세요",
            hintStyle: TextStyle(color: Colors.white),
            labelStyle: TextStyle(color: inputColor)));

    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: 20,
              ),
              inputText2,
              SizedBox(
                height: 20,
              )
            ],
          ),
        ),
      ),
      SizedBox(
        height: 20,
      ),
      ElevatedButton(
        style: ButtonStyle(
          backgroundColor: MaterialStateProperty.all(Colors.redAccent),
          padding: MaterialStateProperty.all(EdgeInsets.all(20)),
        ),
        onPressed: () {
          callAPI(context, ctrlTextParam.text);
        },
        child: Text('alert call'),
      ),
    ];
  }
}

[mobileUtil.dart] - web이 아닌 모든 환경에서 빌드되는 함수


import 'package:flutter/material.dart';

void callAPI(BuildContext context, String sMessage) {
  var snackBar = SnackBar(
    content: Text(sMessage),
  );

  ScaffoldMessenger.of(context).showSnackBar(snackBar);
}

[webUtil.dart] - web 환경에서 빌드되는 함수

import 'dart:js' as js;
import 'package:flutter/material.dart';

// javascript 호출
void callAPI(BuildContext context, String sMessage) {
  js.context.callMethod('alert', ['${sMessage}']);
}
Comments