Trang chủ Kiến Thức Công Nghệ Sử dụng assets trong Flutter package? Tại sao không?
Công Nghệ

Sử dụng assets trong Flutter package? Tại sao không?

Chia sẻ
Sử dụng assets trong Flutter package? Tại sao không?
Chia sẻ

Nếu bạn truy cập vào bài viết này để tìm hiểu cách đưa hình ảnh, phông chữ hoặc các asset khác vào ứng dụng Flutter của mình, thì có thể bạn đã nhầm chỗ. Đùa thôi bạn có thể xem video ở bên dưới nhé! Còn bài viết này mình sẽ hướng dẫn các bạn sử dụng asset trong package (thư viện) của người ta.

1. Bạn nên đặt các asset ở đâu?

Bạn có một hình ảnh, phông chữ hoặc thứ gì đó muốn cung cấp cho các lập trình viên khác sử dụng khi họ dùng package của bạn. Vậy câu hỏi đặt ra là bạn nên đặt nó ở đâu?

Bạn có thể đặt nó vào trong thư mục lib/. Bình thường bạn hay tạo folder assets ở ngoài root project đúng không? Nhưng khi bạn tạo package cho người khác sử dụng thì bạn nên bỏ các assets vào folder lib luôn để họ dễ theo dõi.

Mọi thứ trong thư mục lib/ sẽ được tự động đóng gói với ứng dụng. Những asset đó sẽ có sẵn cho bất kỳ ai sử dụng package của bạn. Với một package developer, bạn thậm chí không cần phải khai báo những asset đó trong pubspec.yaml nếu bạn không sử dụng. Chúng vẫn được đóng gói cùng với package.

Sự lựa chọn khác là tạo một thư mục mới trong dự án chính. Gọi nó là assets  hoặc fonts hoặc bất cứ điều gì bạn muốn.

Assets trong thư mục dự án chính

Tuy nhiên, bất kỳ asset nào không có trong thư mục lib/ sẽ không được thêm vào assets bundle của package trừ khi bạn khai báo chúng trong file pubspec.yaml:

Bash

flutter:
  assets:
    - assets/my_image.jpg
  fonts:
    - family: MyFontFamily
      fonts:
        - asset: assets/my_font.ttf

Bạn có thể xem một số ví dụ để có thể hiểu cách hoạt động của điều này. Tôi sẽ chỉ cho bạn bốn package Flutter khác nhau trên Pub.dev mà mỗi package thực hiện hơi khác một chút. Bạn sẽ thấy cách mà assets được sử dụng như thế nào từ cả quan điểm của tác giả và người dùng package đó.

2. Ví dụ 1: shrine_images

Package shrine_images không thực sự hữu ích ngoài việc cung cấp image assets cho ứng dụng Shrine, một phần của ứng dụng demo Flutter Gallery . Nhưng nó hữu ích khi chỉ ra cách đưa assets vào package Flutter và có lẽ đó là mục đích chính của nó.

Package developer đặt tất cả các asset trong thư mục lib/ như sau:

Bash

shrine_images/lib/
  2.0x/
    0-0.jpg
    1-0.jpg
    10-0.jpg
    ...
  3.0x/
    0-0.jpg
    1-0.jpg
    10-0.jpg
    ...
  0-0.jpg
  1-0.jpg
  10-0.jpg
  ...

Ba density versions khác nhau của mỗi hình ảnh tồn tại. Không có gì khác trong thư mục lib/ ngoại trừ những hình ảnh này. Nếu bạn nhìn vào tệp pubspec.yaml, không có bất kỳ asset nào được đề cập đến. Chỉ cần đưa chúng vào thư mục lib/ là đủ.

2.1 Các developer sử dụng asset trong package như thế nào

Hơi khó để theo cách ứng dụng Shrine sử dụng package, vì vậy, tôi sẽ tạo một ứng dụng đơn giản sử dụng package shrine_images. Khai báo package đó trong file pubspec.yaml như sau:

Dart

name: flutter_assets
description: A Flutter app.

version: 1.0.0+1

environment:
  sdk: ">=2.1.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  shrine_images: ^1.1.2

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true
  assets:
    - packages/shrine_images/10-0.jpg

Lưu ý hai điều:

  1. Tôi đã thêm shrine_images: ^1.1.2 như một dependency.
  2. Tôi đã thêm — packages/shrine_images/10–0.jpg dưới flutter assets. Bạn bắt đầu với package/. Sau đó, bạn cho biết tên package (trong trường hợp này là shrine_images). Sau đó, bạn cung cấp vị trí và tên tệp trong thư mục lib/. Bạn không thêm lib bởi vì điều đó được giả định. Tôi chỉ sử dụng một hình ảnh trong ứng dụng đơn giản của mình. Nếu tôi sử dụng nhiều hình ảnh hơn, tôi sẽ phải liệt kê chúng riêng lẻ (giống như ứng dụng Shrine). Bạn không thể chỉ định thư mục giống như với local assets.

File main.dart của tôi trông giống như sau:‌

Dart

 import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('My App')),
        body: Center(
          child: Image(
            image: AssetImage(
              '10-0.jpg',
              package: 'shrine_images',
            ),
          ),
        ),
      ),
    );
  }
}

Lưu ý rằng bạn không cần phải khai báo thư viện shrine_images ở đầu file.‌‌Để có được hình ảnh, bạn sử dụng AssetImage và cung cấp cho nó tên asset và tên package. Dưới đây là code minh hoạ.

Dart

AssetImage('10-0.jpg', package: 'shrine_images')

Bạn chạy ứng dụng thì sẽ thấy như thế này

Một ứng dụng sử dụng package shrine_images

3. Ví dụ 2: font_awesome_flutter

Package font_awesome_flutter cung cấp một bộ phông chữ với rất nhiều icon hữu ích. Các phông chữ được đóng gói sẵn trong package.

Package này đặt các font asset trong một thư mục con của lib/ như thế này:

Bash

font_awesome_flutter/lib/
  font/
    fa-brands-400.ttf
    fa-regular-400.ttf
    fa-solid-900.ttf
  font_awesome_flutter.dart
  icon_data.dart

Tuy nhiên, vì lập trình viên đang sử dụng các asset trong logic package, họ cũng khai báo các phông chữ dưới dạng asset trong tệp pubspec.yaml:

Yaml

flutter:
  fonts:
    - family: FontAwesomeBrands
      fonts:
        - asset: lib/fonts/fa-brands-400.ttf
          weight: 400
    - family: FontAwesomeRegular
      fonts:
        - asset: lib/fonts/fa-regular-400.ttf
          weight: 400
    - family: FontAwesomeSolid
      fonts:
        - asset: lib/fonts/fa-solid-900.ttf
          weight: 900

Và đây là một đoạn code của nó được sử dụng trong file icon_data.dart:‌

Dart

class IconDataBrands extends IconData {
  const IconDataBrands(int codePoint)
      : super(
          codePoint,
          fontFamily: 'FontAwesomeBrands',
          fontPackage: 'font_awesome_flutter',
        );
}

Package đã làm sẵn điều này giúp người dùng package cảm thấy dễ dàng hơn rất nhiều khi sử dụng.

3.1 Các developer sử dụng asset trong package như thế nào

Lập trình viên ứng dụng chỉ cần thêm font_awesome_flutter  vào file pubspec.yaml của ứng dụng.

Yaml

dependencies:
  font_awesome_flutter: ^8.5.0

Không cần phải khai báo bất kỳ font asset nào. Lập trình viên ứng dụng thậm chí không cần biết tên của các tệp phông chữ.

Bạn chỉ cần import package và sử dụng trực tiếp. Đây là file main.dart cho một bản demo đơn giản:

Dart

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('My App')),
        body: Center(
          child: IconButton(
            icon: Icon(FontAwesomeIcons.wordpress),
            iconSize: 100,
            onPressed: (){},
          ),
        ),
      ),
    );
  }
}

Bạn chỉ cần truyền dữ liệu FontAwesomeIcons.wordpress vào một Icon widget. Điều này giúp cho công việc của lập trình viên ứng dụng trở nên cực kỳ dễ dàng. Chạy ứng dụng ngay bây giờ, bạn sẽ thấy:

Một ứng dụng sử dụng package font_awesome_flutter

4. Ví dụ 3: crypto_font_icons

Package crypto_font_icons tương tự như font_awesome_flutter ở chỗ nó cung cấp một phông chữ tùy chỉnh cho các lập trình viên ứng dụng sử dụng. Lý do tôi đề cập đến nó là package developer đã sử dụng một cấu trúc thư mục khác.

Thay vì đặt font vào thư mục lib/, package developer đã tạo một thư mục fonts trong thư mục package chính như thế này:

Bash

cryptofont-flutter/
  font/
    cryptofont-webfont.ttf
  lib/
    crypto_font_icon_data.dart
    crypto_font_icons.dart

Sau đó, pubspec.yaml trông như thế này:

Yaml

flutter:
  fonts:
    - family: CryptoFont
      fonts:
        - asset: font/cryptofont-webfont.ttf

Bằng cách liệt kê phông chữ dưới dạng asset trong pubspec.yaml, nó vẫn được đưa vào gói asset và do đó sẽ có sẵn cho các lập trình viên ứng dụng sử dụng package này.

4.1 Các developer sử dụng asset trong package như thế nào

Từ quan điểm của lập trình viên ứng dụng, không có vấn đề gì khi package developer không đặt asset vào thư mục lib/. Đó là tất cả những gì được package giấu đi. Chỉ cần phụ thuộc vào nó

Yaml

dependencies:
  crypto_font_icons: ^0.1.0+1

Và sử dụng nó giống như chúng ta đã làm trong ví dụ font_awesome_flutter ở trên.

Dart

import 'package:crypto_font_icons/crypto_font_icons.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('My App')),
        body: Center(
          child: IconButton(
            icon: Icon(CryptoFontIcons.BTC),
            iconSize: 100,
            onPressed: (){},
          ),
        ),
      ),
    );
  }
}

Điều này cho ra:

5. Ví dụ  4: mongol

Trong phiên bản gốc của bài viết này, tôi chỉ có ba ví dụ. Trình bày những ví dụ này giúp tôi học cách tự làm điều đó. Tuy nhiên, tôi đã phát hiện ra khi làm việc trên package rằng các ví dụ trên không đề cập đến cách cung cấp phông chữ. Ví dụ 1 sử dụng widget AssetImage để chỉ định package và ví dụ 2 và 3 sử dụng widget IconData để chỉ định package. Nhưng tôi muốn chia sẻ toàn bộ một phông chữ.

Package của tôi được gọi là mongol. Bạn sẽ không bao giờ sử dụng nó trừ khi bạn là một trong số ít lập trình viên Flutter tạo ứng dụng cho vertical Mongolian text. Tuy nhiên, vì source code nằm trên GitHub, bạn có thể thấy cách tôi cung cấp tệp phông chữ (không chỉ icon data) cho người dùng package.

Tôi đã đưa tệp phông chữ Mongolian (Mông Cổ) vào thư mục lib như thế này:

Yaml

mongol
  lib/
    fonts/
      MQG8F02.ttf

Vì nó nằm trong thư mục lib/ nên nó sẽ tự động được đưa vào gói package. Nhưng vì tôi đang sử dụng nó trong package code để đặt làm phông chữ mặc định cho widget MongolText, tôi cũng đã khai báo nó trong pubspec.yaml:

Yaml

flutter:
  fonts:
    - family: MenksoftQagan
      fonts:
        - asset: lib/fonts/MQG8F02.ttf

MenksoftQagan là tên mô tả. Tôi có thể đã gọi font family là HappyHippos nếu tôi muốn Mẹo tiếp theo là làm thế nào để cung cấp quyền truy cập vào phông chữ đó. Sử dụng MenksoftQagan là không đủ vì không chứa thông tin package. Cách giải quyết là sử dụng string pattern sau khi font family cần thiết:

Dart

'packages/<package_name>/<font_family_name>'

Đối với package của tôi, điều này được dịch sang

Dart

'packages/mongol/MenksoftQagan'

Trong package code, tôi đã tạo một class cho điều này:‌

Dart

class MongolFont {
  static const String qagan = 'packages/mongol/MenksoftQagan';                       }

5.1 Các developer sử dụng asset trong package như thế nào

Vì package sử dụng string ‘packages/mongol/MenksoftQagan’ trong nội bộ, người dùng package hoàn toàn không cần biết về nó.

Khai báo thư viện trong file pubspec.yaml:

Yaml

dependencies:
  mongol: ^0.3.0

main.dart:

Dart

import 'package:flutter/material.dart';
import 'package:mongol/mongol_text.dart';
void main() => runApp(DemoApp());
class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('My App')),
        body: Stack(
          children: <Widget>[
            Center(
              child: MongolText(
                'ᠮᠣᠩᠭᠣᠯ',
                style: TextStyle(fontSize: 100),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Chạy ứng dụng mang lại điều này

một ứng dụng sử dụng package mongol

Tuy nhiên, nếu người dùng ứng dụng muốn sử dụng trực tiếp tệp phông chữ, họ có thể sử dụng string 'packages/mongol/MenksoftQagan' để truy cập nó. Ví dụ: thay thế widget MongolFont bằng widget Text chuẩn:

Dart

Text(
  'ᠮᠣᠩᠭᠣᠯ',
  style: TextStyle(
    fontFamily: 'packages/mongol/MenksoftQagan',
    fontSize: 100,
  ),
),

Nó cho ra:

sử dụng phông chữ trực tiếp từ gói asset package

Để được trợ giúp khi truy cập các loại tệp khác, hãy xem phần Hỏi và Đáp về Stack Overflow này.

Tóm lại:

Thật tuyệt khi các package Pub là open source để chúng ta có thể học hỏi bằng cách xem người khác giải quyết vấn đề tương tự như thế nào. Nếu bạn có cách để cải thiện quy trình thêm asset vào một package, trước tiên hãy kiểm tra vấn đề GitHub này. Và nếu có bất kỳ cải tiến hoặc thông tin nào có thể thêm vào bài viết này, vui lòng cho 200Lab biết nhé.

Bài viết được dịch từ đây.

Bài viết cùng chuyên mục
Tối ưu ứng dụng với cấu trúc dữ liệu cơ bản và bitwise
Công Nghệ

Tối ưu ứng dụng với cấu trúc dữ liệu cơ bản và bitwise

Trong bài viết này, 200Lab sẽ chia sẻ những trường hợp dễ...

Công Nghệ

So sánh Flutter vs React Native: Framework nào đáng học năm 2021

Điểm chung của Flutter, React Native đều là Cross-platform Mobile, build native...

HTTP/2 là gì? So sánh HTTP/2 và HTTP/1
Công Nghệ

HTTP/2 là gì? So sánh HTTP/2 và HTTP/1

Từ khi Internet ra đời, sự phát triển về các giao thức...

Upload File từ Frontend đến Backend mà rất nhiều bạn vẫn đang làm sai!!
Công Nghệ

Upload File từ Frontend đến Backend mà rất nhiều bạn vẫn đang làm sai!!

1. Client encode file (base64) rồi gởi về backend 200Lab đã từng...

Công Nghệ

React Native – Hướng dẫn làm việc với Polyline và Animated-Polyline trên Map

Vẽ đường đi trên bản đồ là một nghiệp vụ vô cùng...

Công Nghệ

Hybrid App và Native App: Những khác biệt to lớn

Bất cứ khi nào một công ty quyết định làm ứng dụng...

Web/System Architecture 101 – Kiến trúc web/hệ thống cơ bản cho người mới
Công Nghệ

Web/System Architecture 101 – Kiến trúc web/hệ thống cơ bản cho người mới

Đây là một kiến trúc cơ bản mà bất kì một người...

Công Nghệ

Tư duy kiến trúc thông qua các trò chơi mà rất nhiều bạn không biết

Tư duy kiến trúc là gì? Tư duy kiến trúc có thể...