国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Flutter實(shí)現(xiàn)Service + UI 全面跨平臺(tái)

這篇具有很好參考價(jià)值的文章主要介紹了Flutter實(shí)現(xiàn)Service + UI 全面跨平臺(tái)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

作者:Karl_wei

前言:

Flutter作為跨平臺(tái)的UI框架,其可行性已經(jīng)被市場(chǎng)所認(rèn)可。UI跨端后,我們自然會(huì)希望一些運(yùn)行在終端的小服務(wù)也能跨端,特別是當(dāng)這個(gè)小服務(wù)還涉及到一些 UI 的展示。

我們希望Flutter能承擔(dān)這個(gè)角色,讓其跨端能力更進(jìn)一步。

需求背景

我們希望在整機(jī)設(shè)備上,運(yùn)行一個(gè)后臺(tái)服務(wù),用戶通過ip地址即可調(diào)用運(yùn)行在設(shè)備上的能力,同時(shí)這個(gè)服務(wù)還能喚起一些UI視圖。
舉個(gè)例子:假如路由器有Android、windows、mac三個(gè)系統(tǒng)的終端,需要提供一個(gè)管理后臺(tái)供用戶設(shè)置,那么路由器的后臺(tái)服務(wù)能力最好是能夠跨這三個(gè)系統(tǒng)的。

web后臺(tái)框架

Dart是支持編寫后臺(tái)服務(wù)的,它提供了 shelf 庫,以處理HTTP請(qǐng)求。整個(gè)項(xiàng)目,我們都是圍繞shelf庫的能力集進(jìn)行開發(fā)的。

靜態(tài)資源 → shelf_static

從需求我們可以了解到,我們需要提供給用戶一個(gè)web管理后臺(tái)進(jìn)行管理,web的資源自然是放在服務(wù)端的。這里我們使用 shelf_static 庫,使用非常的簡(jiǎn)單,就一個(gè)創(chuàng)建靜態(tài)資源操作器的接口。

import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_static/shelf_static.dart';

void main() {
  var handler = createStaticHandler('example/files',
      defaultDocument: 'index.html');

  io.serve(handler, 'localhost', 8080);
}

需要注意的是,必須傳入本地的絕對(duì)路徑,指定默認(rèn)的文件入口。Flutter中,資源一般以asset的方式導(dǎo)入,在編譯過程中以二進(jìn)制的形式打包在應(yīng)用中,并不是普通格式的文件,那么如何傳入給createStaticHandler?
我們通過AssetBundle獲取到這些文件的字節(jié)流,并轉(zhuǎn)化成File保存到指定路徑,這個(gè)路徑就是靜態(tài)資源的路徑。

static Future<String> copyAssets() async {
  int now = DateTime.now().millisecondsSinceEpoch;

  String folderPath = '/sdcard';
  final manifestContent = await rootBundle.loadString('AssetManifest.json');
  final Map<String, dynamic> manifestMap = json.decode(manifestContent);

  final assetList = manifestMap.keys
      .where((String key) => key.startsWith('assets/web'))
      .toList();

  for (final asset in assetList) {
    await copyAsset(asset, folderPath);
  }

  print('移動(dòng)文件耗時(shí) = ${DateTime.now().millisecondsSinceEpoch - now}毫秒');
  return '$folderPath/assets/web';
}

static Future<File> copyAsset(String assetName, String localPath) async {
  int lastSeparatorIndex = assetName.lastIndexOf('/');
  Directory directory = Directory(
      '$localPath${Platform.pathSeparator}${assetName.substring(0, lastSeparatorIndex)}');

  if (!directory.existsSync()) directory.createSync(recursive: true);

  ByteData data = await rootBundle.load(assetName);
  Uint8List bytes = data.buffer.asUint8List();

  final file = File('$localPath${Platform.pathSeparator}$assetName');
  await file.writeAsBytes(bytes);
  return file;
}

調(diào)用copyAssets可以拿到路徑,整個(gè)過程一般不會(huì)超過500ms,視文件體積而定。

路由 → shelf_route

現(xiàn)在我們已經(jīng)可以訪問靜態(tài)資源了,接下來需要提供一系列的接口供前端調(diào)用,這個(gè)時(shí)候我們需要用到 shelf_route 庫。
shelf_route 支持 RESTful 風(fēng)格的路由,可以處理客戶端的 GET、POST、PUT、DELETE 等 HTTP 請(qǐng)求,也可以從 HTTP 路徑中自動(dòng)提取參數(shù)。每個(gè)路由會(huì)提供request請(qǐng)求體,最終返回Response的構(gòu)造函數(shù)即可。
用法很簡(jiǎn)單,下面簡(jiǎn)單演示下如何編寫一個(gè)登錄接口。

import 'package:shelf_router/shelf_router.dart' as self_router;

self_router.Router app = self_router.Router();

// TODO:使用mount,前綴使用模塊命名
app.post(Apis.login, userLogin);
app.post(Apis.resetPwd, resetPassword);
app.post(Apis.signOut, singOutHandle);

Future<Response> userLogin(Request request) async {
  final requestBody = await request.readAsString();
  final Map<String, dynamic> body = json.decode(requestBody);
  Auth auth = Auth();
  var info = await auth.getUserInfo();
  if (info.$1 == body['username'] && info.$2 == body['password']) {
    String token = await auth.generateToken(body['username'], body['password']);
    return Response.ok(
        BaseResponse(Code.success, data: {'token': token}, msg: '登錄成功')
            .toString());
  } else {
    return Response.ok(BaseResponse(Code.reject, msg: '賬號(hào)密碼錯(cuò)誤').toString());
  }
}

中間件 → helf_multipart

一般后臺(tái)服務(wù),都需要對(duì)部分接口進(jìn)行鑒權(quán)操作,這部分的邏輯一般是通用的,一般開發(fā)過程中我們會(huì)用到中間件的機(jī)制。
中間件通常被用于攔截和處理請(qǐng)求與響應(yīng)之間的過程,以實(shí)現(xiàn)一些公共的應(yīng)用邏輯和功能,比如認(rèn)證、日志記錄、錯(cuò)誤處理等等。
在Flutter中,我們使用 shelf_multipart 這個(gè)庫,通過Pipeline可以加上Middleware,這個(gè)中間件是應(yīng)用于所有路由的,因此某些接口不需要這個(gè)中間件操作,直接在白名單內(nèi)過濾即可;innerHandler則是執(zhí)行對(duì)應(yīng)的響應(yīng)操作。

var middleHandler = const Pipeline().addMiddleware(authMiddleware); // 添加中間件

Middleware authMiddleware = (Handler innerHandler) {
  return (Request request) async {
    String path = request.url.path.split('?').first;
    if (!whitelist.contains(path)) { // 過濾白名單
      String? token = request.headers['Authorization'];
      Auth auth = Auth();
      var authVerify = await auth.verifyToken(token); // 驗(yàn)證token
      if (!authVerify.$1) {
        return Response.unauthorized(
            BaseResponse(Code.reject, msg: authVerify.$2!).toString());
      } else {
        auth.updateTokenTime(); // 有操作則續(xù)費(fèi)token時(shí)長
      }
    }
    final response = await innerHandler(request);
    return response;
  };
};

websocket → shelf_websocket

上面所寫的都是提供HTTP服務(wù)的,在業(yè)務(wù)中也經(jīng)常存在需要websocket,我們使用 shelf_websocket 庫。跟靜態(tài)資源一樣,單一的能力只需要提供最簡(jiǎn)單的接口:webSocketHandler。

import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

void main() {
  var webSocketHandler = webSocketHandler((webSocket) {
    webSocket.stream.listen((message) {
      webSocket.sink.add("echo $message");
    });
  });

  shelf_io.serve(handler, 'localhost', 8080).then((server) {
    print('Serving at ws://${server.address.host}:${server.port}');
  });
}

最后我們需要把所有的handler都整合成一個(gè)服務(wù),傳給io.serve;

Handler cascadeHandler = Cascade().add(handler).add(app).add(webSocketHandler).handler; // 合并靜態(tài)資源、路由、websocket

// 合入中間件
// 創(chuàng)建本機(jī)服務(wù),端口8888
await io.serve(middleHandler.addHandler(cascadeHandler), '0.0.0.0', 8888);

通用服務(wù)能力

用戶鑒權(quán)

一般這種小型本機(jī)服務(wù),登錄用戶都是互斥的,用戶權(quán)限管理我們可以簡(jiǎn)單的使用:hive + JWT token。
采用hive來保存用戶信息,通過 dart_jsonwebtoken 庫生成token,然后在中間件攔截,對(duì)header中攜帶的token信息進(jìn)行驗(yàn)證,從而達(dá)到鑒權(quán)的目的。

Future<String> generateToken(String userName, String password) async {
  Box box = await Hive.openBox(_boxName);
  JWT jwt = JWT(
    {
      'userName': userName,
      'password': password,
    },
    jwtId: const Uuid().v4(),
  );
  String token = jwt.sign(SecretKey(_secretKey));
  await box.put(Constant.userNameKey, userName);
  await box.put(Constant.pwdKey, password);
  await box.put(Constant.tokenKey, token);
  updateTokenTime();
  return token;
}

文件上傳

一般web后臺(tái),都會(huì)把文件資源存儲(chǔ)在另一個(gè)文件服務(wù)中,比如:七牛云。不過既然是小服務(wù),我們也希望dart能擁有這個(gè)能力。
文件上傳的路由,參數(shù)一般都是form表單;當(dāng)解析到request為isMultipart時(shí),則對(duì)文件流進(jìn)行讀取,并寫到本地路徑中。
特別需要注意的是:Dart是單線程,寫文件這種耗時(shí)io操作,必須使用IOSink + stream方式寫入,不然內(nèi)存會(huì)拉滿,大文件會(huì)直接讓應(yīng)用崩潰。

app.post(Apis.upload, uploadFile);

Future<Response> uploadFile(Request request) async {
  if (!request.isMultipart) {
    return Response.ok('Not a multipart request');
  } else if (request.isMultipartForm) {
    String? filename;
    String? path;
    await for (var part in request.parts) {
      var contentDisposition = part.headers['content-disposition'];
      filename = RegExp(r'filename="([^"]*)"')
          .firstMatch(contentDisposition!)
          ?.group(1);
      path = '${await CommonUtils.getDownloadPath()}$filename';
      File? file = File(path);

      IOSink sink = file.openWrite();
      await sink.addStream(part);
      await sink.flush();
      await sink.close();
    }
    return Response.ok(
        BaseResponse(Code.success, data: {"filePath": path}).toString());
  } 
}

運(yùn)行機(jī)制:Service + UI

使用Flutter編寫這種后臺(tái)服務(wù),還有一個(gè)好處是可以跨平臺(tái)的展示UI。比如:需要后臺(tái)彈出一些設(shè)置成功的toast,這個(gè)時(shí)候就非常的方便了。

Android平臺(tái),我們在Android Service上創(chuàng)建一個(gè)Flutter Engine,可以直接執(zhí)行到Dart代碼;當(dāng)我們需要展示UI的時(shí)候,只需要通過我們的多窗口插件打開一個(gè)懸浮窗即可。

Windows平臺(tái),我們目前還沒有在C++ 服務(wù)上運(yùn)行dart代碼,而是通過把窗口設(shè)置為0在后臺(tái)運(yùn)行著;當(dāng)需要展示UI的時(shí)候,恢復(fù)窗口大小,然后進(jìn)入指定的UI界面即可。

結(jié)語

在常規(guī)業(yè)務(wù)場(chǎng)景基本都不會(huì)使用dart開發(fā)后臺(tái)服務(wù);針對(duì)整機(jī)小型服務(wù)的需求,我認(rèn)為Flutter還是挺香的,內(nèi)存不存在隱患,還能前后端都跨平臺(tái)。
本篇文章,分享了整個(gè)shelf框架編寫web服務(wù)的經(jīng)驗(yàn),我認(rèn)為在這個(gè)小眾的類目中這篇文章算是非常齊全了;同時(shí)我們也驗(yàn)證了Flutter/Dart在web服務(wù)的可行性,F(xiàn)lutter的業(yè)務(wù)價(jià)值進(jìn)一步提升~

Android 學(xué)習(xí)筆錄

Android 性能優(yōu)化篇:https://qr18.cn/FVlo89
Android 車載篇:https://qr18.cn/F05ZCM
Android 逆向安全學(xué)習(xí)筆記:https://qr18.cn/CQ5TcL
Android Framework底層原理篇:https://qr18.cn/AQpN4J
Android 音視頻篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(內(nèi)含Compose):https://qr18.cn/A0gajp
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
OkHttp 源碼解析筆記:https://qr18.cn/Cw0pBD
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知識(shí)體:https://qr18.cn/CyxarU
Android 核心筆記:https://qr21.cn/CaZQLo
Android 往年面試題錦:https://qr18.cn/CKV8OZ
2023年最新Android 面試題集:https://qr18.cn/CgxrRy
Android 車載開發(fā)崗位面試習(xí)題:https://qr18.cn/FTlyCJ
音視頻面試題錦:https://qr18.cn/AcV6Ap文章來源地址http://www.zghlxwxcb.cn/news/detail-651032.html

到了這里,關(guān)于Flutter實(shí)現(xiàn)Service + UI 全面跨平臺(tái)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 二十三種設(shè)計(jì)模式全面解析-橋接模式的高級(jí)應(yīng)用:構(gòu)建靈活的跨平臺(tái)UI框架

    在軟件開發(fā)的世界中,橋接模式(Bridge Pattern)作為一種設(shè)計(jì)模式,旨在將抽象部分與實(shí)現(xiàn)部分分離,從而使它們可以獨(dú)立地變化。這一模式的應(yīng)用不僅有助于提高代碼的可維護(hù)性,還在一些復(fù)雜的場(chǎng)景中展現(xiàn)出其真正的價(jià)值。 前面一篇文章中,我們介紹了什么是橋接模式?

    2024年02月05日
    瀏覽(35)
  • 【Flutter跨平臺(tái)插件開發(fā)】如何實(shí)現(xiàn)kotlin跟C++的相互調(diào)用

    在 Kotlin 中,可以使用 JNI (Java Native Interface) 來調(diào)用 C++ 代碼 調(diào)用步驟: 創(chuàng)建 C++ 文件并實(shí)現(xiàn)函數(shù)。 在 Kotlin 中聲明需要調(diào)用的 native 函數(shù)并加載 native 庫。 調(diào)用示例 Flutter 插件項(xiàng)目的例子 在 Flutter 插件中引用已有的 C++ 源碼需要以下步驟: 首先,在 Flutter 插件的 android 目錄下

    2024年01月25日
    瀏覽(100)
  • Flutter 實(shí)戰(zhàn):構(gòu)建跨平臺(tái)應(yīng)用

    Flutter 實(shí)戰(zhàn):構(gòu)建跨平臺(tái)應(yīng)用

    Flutter是由Google開發(fā)的一款開源移動(dòng)應(yīng)用開發(fā)框架,它可以幫助開發(fā)者在iOS和Android平臺(tái)上快速、高效地開發(fā)應(yīng)用。Flutter使用Dart語言作為開發(fā)語言,具有跨平臺(tái)兼容性高、開發(fā)效率快、性能優(yōu)異等特點(diǎn)。本文將通過實(shí)戰(zhàn)案例,介紹如何使用Flutter構(gòu)建跨平臺(tái)應(yīng)用。 在開始Flutte

    2024年02月05日
    瀏覽(1262)
  • Flutter:構(gòu)建跨平臺(tái)應(yīng)用的未來選擇

    隨著移動(dòng)設(shè)備的普及和技術(shù)的不斷發(fā)展,跨平臺(tái)移動(dòng)應(yīng)用開發(fā)成為了一個(gè)熱門的需求。Flutter作為一款由Google開發(fā)的開源移動(dòng)應(yīng)用開發(fā)框架,受到了越來越多的關(guān)注。本文將帶你了解Flutter的優(yōu)勢(shì)、應(yīng)用場(chǎng)景以及如何使用Flutter進(jìn)行開發(fā)。 一、Flutter的優(yōu)勢(shì) 1.跨平臺(tái):Flutter使用

    2024年02月09日
    瀏覽(97)
  • Flutter:跨平臺(tái)移動(dòng)應(yīng)用開發(fā)的未來

    Flutter:跨平臺(tái)移動(dòng)應(yīng)用開發(fā)的未來

    Flutter的背景和概述 Flutter是由Google開發(fā)的一個(gè)開源UI工具包,用于構(gòu)建漂亮、快速且高度可定制的移動(dòng)應(yīng)用程序。它于2017年首次發(fā)布,并迅速引起了開發(fā)者們的關(guān)注。Flutter采用了一種全新的方法來構(gòu)建用戶界面,通過使用自繪UI技術(shù),可以實(shí)現(xiàn)高性能的跨平臺(tái)應(yīng)用開發(fā)。 Fl

    2024年01月22日
    瀏覽(91)
  • 通過堅(jiān)果云、KeePassXC、keepass2android實(shí)現(xiàn)跨平臺(tái)的密碼管理方案

    通過堅(jiān)果云、KeePassXC、keepass2android實(shí)現(xiàn)跨平臺(tái)的密碼管理方案

    KeePassXC、keepass2android都是屬于一個(gè)免費(fèi)的密碼管理軟件,但是密碼的數(shù)據(jù)庫文件是基于本地設(shè)備的、難做到Windows和Android使用同一個(gè)密碼數(shù)據(jù)庫文件的要求,但他們都支持使用對(duì)方的數(shù)據(jù)庫文件,堅(jiān)果云支持第三方應(yīng)用授權(quán)WebDAV,所以我們借用堅(jiān)果云實(shí)現(xiàn)一個(gè)把數(shù)據(jù)庫文件放

    2024年02月06日
    瀏覽(37)
  • 從零基礎(chǔ)到精通Flutter開發(fā):一步步打造跨平臺(tái)應(yīng)用

    從零基礎(chǔ)到精通Flutter開發(fā):一步步打造跨平臺(tái)應(yīng)用

    ?? 個(gè)人網(wǎng)站:【工具大全】【游戲大全】【神級(jí)源碼資源網(wǎng)】 ?? 前端學(xué)習(xí)課程:??【28個(gè)案例趣學(xué)前端】【400個(gè)JS面試題】 ?? 尋找學(xué)習(xí)交流、摸魚劃水的小伙伴,請(qǐng)點(diǎn)擊【摸魚學(xué)習(xí)交流群】 導(dǎo)言 Flutter是一種流行的開發(fā)框架,可以用來構(gòu)建美觀、高性能且跨平臺(tái)的移動(dòng)應(yīng)

    2024年02月08日
    瀏覽(95)
  • 我想開發(fā)一款跨平臺(tái)桌面軟件,請(qǐng)告訴我qt、electron、tauri、pyqt、flutter分別適合開發(fā)哪些跨平臺(tái)桌面

    我想開發(fā)一款跨平臺(tái)桌面軟件,請(qǐng)告訴我qt、electron、tauri、pyqt、flutter分別適合開發(fā)哪些跨平臺(tái)桌面

    不同的跨平臺(tái)桌面開發(fā)工具適用于不同的應(yīng)用場(chǎng)景和開發(fā)者需求。以下是關(guān)于 Qt、Electron、Tauri、PyQt、Flutter 的簡(jiǎn)要說明,以幫助你更好地選擇適合你項(xiàng)目的工具: Qt: 適用場(chǎng)景: Qt 是一個(gè)強(qiáng)大的 C++ 框架,適用于開發(fā)需要高性能和原生外觀的桌面應(yīng)用。它具有廣泛的平臺(tái)支持

    2024年02月22日
    瀏覽(95)
  • 開發(fā)跨平臺(tái)APP,是用Flutter還是React Native開發(fā)框架?

    開發(fā)跨平臺(tái)APP,是用Flutter還是React Native開發(fā)框架?

    ?隨著移動(dòng)互聯(lián)網(wǎng)的飛速發(fā)展,對(duì)于開發(fā)人員而言,如何快速地開發(fā)出兼容不同平臺(tái)(iOS、Android)的應(yīng)用,成為了一個(gè)重要的問題。 跨平臺(tái)應(yīng)用程序開發(fā)框架的好處: 1. 一個(gè)App適用于多個(gè)設(shè)備; 2. 一個(gè)App適用于多個(gè)平臺(tái); 3. 一個(gè)App可以在多個(gè)應(yīng)用商店中發(fā)布; 4. 只需編寫

    2024年02月15日
    瀏覽(93)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包