当前位置: 首页>编程语言>正文

插件开发与热重载原理

Flutter鐨勪笁鏂瑰伐鍏锋湁涓ょ锛屼竴绉嶆槸鎻掍欢锛圥lugin锛夛紝涓€绉嶆槸鍖?/code>锛圥ackage锛夈€傝繖涓ょ宸埆鍦ㄤ簬Plugin涓嶄粎鍖呭惈Dart浠g爜锛岃繕鍖呭惈浜?code>iOS浠ュ強瀹夊崜鐨勫師鐢熶唬鐮侊紝姣斿甯歌鐨?code>image_picker锛涜€?code>Package浠呬粎鏄?code>Dart浠g爜搴撱€?/p>

插件开发与热重载原理,第1张
鏀寔绌哄畨鍏ㄧ殑搴?/div>

package寮€鍙?/h2>

涓嬮潰鎴戜滑寮€鍙戜竴涓?code>鏀寔绌哄畨鍏?/code>鐨勫簱锛屽氨鐢ㄤ箣鍓嶇殑wechat_demo宸ョ▼涓?code>閫氳褰曢〉闈?/code>鍙充晶鐨?code>IndexBar杩涜缁冧範

  • 鏂板缓Package宸ョ▼logic_package_demo锛屾敞鎰?code>Project type閫夋嫨Package
插件开发与热重载原理,第2张
  • 鏌ョ湅宸ョ▼鐩綍锛屽彂鐜板苟涓嶅寘鍚?code>iOS銆?code>瀹夊崜鐩綍
插件开发与热重载原理,第3张
  • 绌哄畨鍏ㄧ増鏈?/code>鐩稿叧閰嶇疆渚濈劧鍦?code>pubspec.yaml鏂囦欢涓?/li>
  • Package宸ョ▼寮曠敤璧勬簮鍥剧墖锛?code>New -> Directory鏂板缓images鐩綍锛屾妸鍥剧墖璧勬簮鏀惧叆鐩綍
插件开发与热重载原理,第4张
鏂板缓鍥剧墖鐩綍
  • pubspec.yaml鏂囦欢杩涜閰嶇疆锛屽紩鍏ュ浘鐗囪祫婧?/li>
插件开发与热重载原理,第5张
鍥剧墖璧勬簮閰嶇疆
  • 鍗曞厓娴嬭瘯test鐩綍涓嬬殑鎶ラ敊鍏堝垹鎺?/li>
插件开发与热重载原理,第6张
鍒犻櫎閫変腑鐨勫崟鍏冩祴璇曚唬鐮?/div>
  • logic_package_demo.dart鏂囦欢鍐呭
library logic_package_demo;

import 'package:flutter/material.dart';

class IndexBar extends StatefulWidget {
  // 瀵瑰鎻愪緵鍥炶皟锛屽憡璇塮riends_page褰撳墠閫変腑鐨勬槸鏍囪瘑
  final void Function(String str) indexBarCallBack;

  const IndexBar({required this.indexBarCallBack, Keykey}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _IndexBarState();
}

// 鑾峰彇閫変腑鐨刬tem鐨勫瓧绗?!
// context灏辨槸widget涓殑Element
int getIndex(BuildContext context, Offset globalPosition) {
  // 鑾峰彇褰撳墠灏忛儴浠剁殑鐩掑瓙锛岀被鍨嬪己杞琑enderBox
  RenderBox box = context.findRenderObject() as RenderBox;
  // 鑾峰彇y鍊?globalToLocald褰撳墠浣嶇疆璺濈閮ㄤ欢鍘熺偣(宸︿笂瑙?鐨勪綅缃?
  double y = box.globalToLocal(globalPosition).dy;
  // 绠楀嚭瀛楃楂樺害
  var itemHeight = screenHeigth(context) / 2 / INDEX_WORDS.length;
  // 绠楀嚭绗嚑涓猧tem, clamp绾︽潫index鑼冨洿鍊?
  int index = (y ~/ itemHeight).clamp(0, INDEX_WORDS.length - 1);
  return index;
}

class _IndexBarState extends State<IndexBar> {
  // 绱㈠紩鏉¢€変腑 鑳屾櫙鑹蹭笌鏂囧瓧棰滆壊
  Color _bkColor = Color.fromRGBO(1, 1, 1, 0.0);
  Color _textColor = Colors.black;

  // 娣诲姞鍥剧墖鎸囩ず鍣╕鍊硷紝鏄剧ず绱㈠紩鏍囪瘑锛屾槸鍚︽樉绀虹瓑灞炴€?
  double _indicatorY = 0.0;
  String _indicatorText = 'A';
  bool _indicatorHidden = true;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    // 涓庣晫闈㈢浉鍏崇殑鏁版嵁瑕佹斁鍏uild涓?
    final List<Widget> words = [];
    for (int i = 0; i < INDEX_WORDS.length; i++) {
      words.add(Expanded(
          child: Text(
        INDEX_WORDS[i],
        style: TextStyle(fontSize: 10, color: _textColor),
      )));
    }

    // TODO: implement build
    return Positioned(
      right: 0.0,
      top: screenHeigth(context) / 8,
      height: screenHeigth(context) / 2,
      width: 120,
      // 娣诲姞鎵嬪娍
      child: Row(
        children: [
          Container(
            alignment: Alignment(0, _indicatorY),
            width: 100,
            // color: Colors.red,
            child: _indicatorHidden
                null
                : Stack(
                    // 璁╂皵娉″眳涓?
                    alignment: Alignment(-0.2, 0),
                    children: [
                      Image(
                        image: AssetImage('images/姘旀场.png'),
                        width: 60,
                      ),
                      Text(
                        _indicatorText,
                        style: TextStyle(fontSize: 35, color: Colors.white),
                      )
                    ],
                  ),
          ), //鎸囩ず鍣?
          GestureDetector(
            // 鎷栨嫿鎵嬪娍
            onVerticalDragUpdate: (DragUpdateDetails details) {
              // String str = getIndex(context, details.globalPosition);
              // print('閫変腑鐨勬槸$str');
              int index = getIndex(context, details.globalPosition);
              widget.indexBarCallBack(INDEX_WORDS[index]);
              setState(() {
                _indicatorY = 2.2 / INDEX_WORDS.length * index - 1.1;
                _indicatorText = INDEX_WORDS[index];
                _indicatorHidden = false;
              });
            },
            // 鐐瑰嚮绱㈠紩
            onVerticalDragDown: (DragDownDetails details) {
              int index = getIndex(context, details.globalPosition);
              widget.indexBarCallBack(INDEX_WORDS[index]);
              setState(() {
                _indicatorY = 2.2 / INDEX_WORDS.length * index - 1.1;
                _indicatorText = INDEX_WORDS[index];
                _indicatorHidden = false;
                _bkColor = Color.fromRGBO(1, 1, 1, 0.5);
                _textColor = Colors.white;
              });
            },
            // 鐐瑰嚮缁撴潫,棰滆壊鍊艰繕鍘?
            onVerticalDragEnd: (DragEndDetails details) {
              setState(() {
                _indicatorHidden = true;
                _bkColor = Color.fromRGBO(1, 1, 1, 0.0);
                _textColor = Colors.black;
              });
            },
            child: Container(
              // 璁剧疆瀹藉害锛岃鍙充晶绱㈠紩灞呬腑
              width: 20,
              color: _bkColor,
              child: Column(
                children: words,
              ),
            ),
          ), //绱㈠紩鏉?
        ],
      ),
    );
  }
}

//涓婚鑹?
//const淇グ鐨勫父閲忥紝鍚嶇О棣栧瓧姣嶅彲浠ユ槸澶у啓
const Color WeChatThemeColor = Color.fromRGBO(220, 220, 220, 1.0);

//灞忓箷瀹藉害
//灞忓箷瀹藉害鏄€氳繃璁$畻鏉ヨ幏鍙栵紝涓嶈兘瀹氫箟鎴愬父閲忥紱棣栧瓧姣嶉渶瑕佸皬鍐?
double screenWidth(BuildContext context) => MediaQuery.of(context).size.width;

double screenHeigth(BuildContext context) => MediaQuery.of(context).size.height;

const INDEX_WORDS = [
  '馃攳',
  '鈽?,
  'A',
  'B',
  'C',
  'D',
  'E',
  'F',
  'G',
  'H',
  'I',
  'J',
  'K',
  'L',
  'M',
  'N',
  'O',
  'P',
  'Q',
  'R',
  'S',
  'T',
  'U',
  'V',
  'W',
  'X',
  'Y',
  'Z'
];
  • Package鍖呭彂甯冨墠閰嶇疆
插件开发与热重载原理,第7张
鍙戝竷鍓嶉厤缃?/div>
  • Package鍖呰繘琛屽彂甯?/li>
// 杩涘叆logic_package_demo宸ョ▼鐩綍
$ cd /Users/wn/Desktop/logic_package_demo
// 妫€鏌ackage鍖?
$ flutter packages pub publish --dry-run
插件开发与热重载原理,第8张
妫€鏌ュ寘

姣斿pubspec.yaml鏂囦欢涓殑homepage娌℃湁閰嶇疆锛屾鏌ョ殑鏃跺€欏氨浼氭姤閿欍€?/p>

// Package鍖呰繘琛屽彂甯?
$ flutter packages pub publish

娉ㄦ剰锛?/strong>鐩墠鍙戝竷鎻掍欢鍜屽寘閮介渶瑕?code>Google璐﹀彿锛屽悓鏃堕渶瑕佺炕澧欍€?/p>

褰撳嚭鐜颁笅闈㈡彁绀猴紝闇€瑕佷綘浣跨敤娴忚鍣ㄨ闂彁绀轰腑鐨勯摼鎺ワ紝鐢ㄤ綘鐨?code>Google璐﹀彿鎺堟潈銆?/p>

插件开发与热重载原理,第9张

鏈夋椂灏辩畻鏄炕澧欎篃骞朵笉鑳借В鍐抽棶棰橈紝鍥犱负鎴戜滑杩橀厤缃簡鐩稿叧鐨勯暅鍍忋€?code>Flutter瀹樻柟灏卞缓璁繃闀滃儚鐨勯厤缃紝鎵€浠ユ垜浠湪鍙戝竷鎻掍欢鎴栬€呭寘鐨勬椂鍊欙紝灏变細鍥犱负闀滃儚鍑虹幇涓嬮潰閿欒锛?/p>

插件开发与热重载原理,第10张

瑙e喅鍔炴硶锛?code>鎸囧畾鏈嶅姟鍣ㄥ彂甯?/code>

$ flutter packages pub publish --server=https://pub.dartlang.org
  • 璇佷功闂鎶ラ敊
插件开发与热重载原理,第11张

鍙戝竷鍖呯殑涓€涓増鏉冮棶棰橈紝杩欎釜璇佷功闇€瑕佸湪Github浠撳簱涓垱寤恒€?/p>

插件开发与热重载原理,第12张
閰嶇疆璇佷功鏂囦欢
  • Github鑾峰彇璇佷功
插件开发与热重载原理,第13张
鍒涘缓浠撳簱
插件开发与热重载原理,第14张
鏌ョ湅浠撳簱
插件开发与热重载原理,第15张
鑾峰彇璇佷功

鎶婅瘉涔︽枃浠跺唴瀹瑰鍒跺埌LICENSE鏂囦欢銆?/p>

  • 瑙e喅瀹屼笂闈㈣瘉涔﹂棶棰橈紝鍐嶆鍙戝竷
插件开发与热重载原理,第16张
鍙戝竷鎴愬姛

绛夊緟20 ~ 25鍒嗛挓锛宲ub.dev缃戠珯灏辫兘鎼滅储鍒版垜浠彂甯冪殑logic_package_demo鍖呫€?/p>

wechat_demo浣跨敤鎴戜滑鍙戝竷鐨勫寘
  • pubspec.yaml鏂囦欢杩涜閰嶇疆锛岀偣鍑?code>Pub get寮曞叆
插件开发与热重载原理,第17张
寮曞叆鎴戜滑涓婁紶鐨勫寘
插件开发与热重载原理,第18张
寮曞叆鎴愬姛
  • friends_page.dart鏂囦欢杩涜寮曞叆浣跨敤
// 瀵煎叆澶存枃浠?
import 'package:login_package_demo/login_package_demo.dart' as login;
插件开发与热重载原理,第19张

杩欎釜鏃跺€欎細鏈変竴涓棶棰橈紝鐐瑰嚮Pub get鐨勬椂鍊欏彧鏄妸浠g爜寮曞叆鍒颁簡wechat_demo椤圭洰锛屽浘鐗囪祫婧愬苟娌℃湁寮曞叆锛岃繖涓椂鍊欎娇鐢?code>Package鍖呭氨浼氭姤閿欙紝涓嬮潰杩涜浼樺寲...

浼樺寲package

鎶?code>鏈湴璧勬簮鏂囦欢涔熶笂浼犲埌鏈嶅姟鍣紝璁╀娇鐢ㄨ€呰兘澶熸垚鍔熷紩鍏ュ浘鐗囪祫婧?/code>

  • images鍥剧墖璧勬簮瑕佹斁鍏?code>lib鐩綍涓?br>

    插件开发与热重载原理,第20张
  • 浣跨敤鍥剧墖璧勬簮鐨勬椂鍊欐寚瀹?code>Package鍖呭悕

// 鍘籰ogic_package_demo鍖呬腑鎵惧埌鍥剧墖杩涜鍔犺浇
const AssetImage('images/bubble.png', package: 'logic_package_demo'),
  • 閲嶆柊鍙戝竷logic_package_demo鍖咃紙pubspec.yaml鏂囦欢瑕佹妸version: 0.0.1 鏇存敼涓?0.0.2 # 椤圭洰鐗堟湰锛岃繘琛岀増鏈崌绾э紝鍚﹀垯涓嶈兘鍙戝竷锛?/li>
插件开发与热重载原理,第21张
CHANGELOG.md鏂囦欢涔熷崌绾у埌0.0.2鐗堟湰
  • 鍙戝竷瀹屾垚涔嬪悗锛?code>wechat_demo宸ョ▼杩涜寮曞叆浣跨敤
插件开发与热重载原理,第22张
鎸囧畾0.0.2鐗堟湰
插件开发与热重载原理,第23张
閰嶇疆鍥剧墖璧勬簮

杩欓噷鐨勫浘鐗囪祫婧愬紩鐢?code>鎸囧畾鍒颁簡鍏蜂綋鍥剧墖锛屼笉鎺ㄨ崘杩欑鏂瑰紡銆?/p>

  • logic_package_demo.dart涓殑IndexBar杩涜鎵╁睍锛屽厑璁稿闈紶鍏ュ浘鐗?/li>
class IndexBar extends StatefulWidget {
  // 瀵瑰鎻愪緵鍥炶皟锛屽憡璇塮riends_page褰撳墠閫変腑鐨勬槸鏍囪瘑
  final void Function(String str) indexBarCallBack;
  final ImageProviderimage;
  const IndexBar({required this.indexBarCallBack, this.image, Keykey}) : super(key: key);
......

// 璁╂皵娉″眳涓?
alignment: Alignment(-0.2, 0),
children: [
  Image(
    // widget.image浣跨敤澶栭潰浼犲叆鐨刬mage
    image: widget.image ?AssetImage('images/姘旀场.png', package: 'logic_package_demo'),
    width: 60,
  ),
  Text(
    _indicatorText,
    style: TextStyle(fontSize: 35, color: Colors.white),
  )
],
Pub.dev缃戠珯鏌ョ湅鎻愬崌鍖呯殑鍒嗘暟杩涜浼樺寲
插件开发与热重载原理,第24张
  • 娣诲姞椤圭洰鎻忚堪
  • 娣诲姞example锛屼娇鐢?code>Package鍖呯殑绀轰緥
  • 澧炲姞API鏁伴噺

涓嬮潰涓昏鏄坊鍔犱娇鐢ㄧず渚嬭繘琛屼紭鍖栵紝鎻愬崌鍖呯殑璇勫垎

  • 鏂板缓package_example绌哄伐绋嬶紝璺?code>logic_package_demo鏀惧叆鍚屼竴鐩綍涓?/li>
  • pubspec.yaml鏂囦欢杩涜閰嶇疆锛屽苟鐐瑰嚮Pub get杩涜寮曞叆
插件开发与热重载原理,第25张
  • 浣跨敤wechat_demo涓殑FriendsPage椤甸潰锛屽苟杩涜淇敼
<!-- package_example宸ョ▼鐨刴ain.dart鏂囦欢 -->
import 'package:flutter/material.dart';
import 'package:logic_package_demo/logic_package_demo.dart' as logic;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Keykey}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: FriendsPage(),
    );
  }
}

class _FriendCell extends StatelessWidget {
  const _FriendCell(
      {this.imageUrl, this.name, this.groupTitle, this.imageAssets});

  final StringimageUrl;
  final Stringname;
  final StringgroupTitle;
  final StringimageAssets;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          alignment: Alignment.centerLeft,
          padding: EdgeInsets.only(left: 10),
          height: groupTitle != null 30 : 0,
          // 浣跨敤logic_package_demo搴撲腑閰嶇疆鐨勫父閲?
          color: logic.WeChatThemeColor,
          child: groupTitle != null
              Text(
                  groupTitle!,
                  style: const TextStyle(color: Colors.grey),
                )
              : null,
        ), //澶撮儴
        Container(
          color: Colors.white,
          child: Row(
            children: [
              Container(
                margin: EdgeInsets.all(10),
                width: 34,
                height: 34,
                decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(6.0),
                    image: DecorationImage(
                      image: imageUrl != null
                          NetworkImage(imageUrl!)
                          : AssetImage(imageAssets!,
                              package: 'logic_package_demo') as ImageProvider,
                    )),
              ), //鍥剧墖
              Container(
                // color: Colors.red,
                width: logic.screenWidth(context) - 54,
                child: Column(
                  children: [
                    Container(
                      alignment: Alignment.centerLeft,
                      height: 54,
                      child: Text(
                        name!,
                        style: TextStyle(fontSize: 18),
                      ),
                    ),
                    Container(
                      height: 0.5,
                      color: logic.WeChatThemeColor,
                    ), //涓嬪垝绾?
                  ],
                ),
              ), //鏄电О+涓嬪垝绾?
            ],
          ),
        ), //Cell鐨勫唴瀹?
      ],
    );
  }
}

class FriendsPage extends StatefulWidget {
  @override
  _FriendsPageState createState() => _FriendsPageState();
}

class _FriendsPageState extends State<FriendsPage>
    with AutomaticKeepAliveClientMixin<FriendsPage> {
  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;

  double _cellHeight = 54.5;
  double _groupHeight = 30.0;

  //瀛楀吀锛岄噷闈㈡斁item鍜岄珮搴︾殑瀵瑰簲鐨勬暟鎹€?
  final Map _groupOffsetMap = {
    logic.INDEX_WORDS[0]: 0.0,
    logic.INDEX_WORDS[1]: 0.0,
  };

  final List<Friends> _headerData = [
    Friends(imageAssets: 'images/鏂扮殑鏈嬪弸.png', name: '鏂扮殑鏈嬪弸'),
    Friends(imageAssets: 'images/缇よ亰.png', name: '缇よ亰'),
    Friends(imageAssets: 'images/鏍囩.png', name: '鏍囩'),
    Friends(imageAssets: 'images/鍏紬鍙?png', name: '鍏紬鍙?),
  ];
  final List<Friends> _listDatas = [];
  // 鎳掑姞杞?
  late ScrollController _scrollController;
  @override
  void initState() {
    super.initState();

    _scrollController = ScrollController();
    //鍒涘缓鏁版嵁
    _listDatas
      ..addAll(datas)
      ..addAll(datas);
    //鎺掑簭
    _listDatas.sort((Friends a, Friends b) {
      return a.indexLetter!.compareTo(b.indexLetter!);
    });
    var _groupOffset = _cellHeight * _headerData.length;
    //杩涜繃寰幆璁$畻锛屽皢姣忎竴涓ご鐨勪綅缃畻鍑烘潵銆傛斁鍏ュ瓧鍏?
    for (int i = 0; i < _listDatas.length; i++) {
      if (i < 1) {
        //绗竴涓猚ell涓€瀹氭湁澶达紒
        _groupOffsetMap.addAll({_listDatas[i].indexLetter: _groupOffset});
        //淇濆瓨瀹屼簡鍐嶅姞_groupOffset
        _groupOffset += _cellHeight + _groupHeight;
      } else if (_listDatas[i].indexLetter == _listDatas[i - 1].indexLetter) {
        //涓嶅悓瀛橈紝鍙渶瑕佸姞Cell鐨勯珮搴?
        _groupOffset += _cellHeight;
      } else {
        _groupOffsetMap.addAll({_listDatas[i].indexLetter: _groupOffset});
        //淇濆瓨瀹屼簡鍐嶅姞_groupOffset
        _groupOffset += _cellHeight + _groupHeight;
      }
    }
  }

  Widget _itemForRow(BuildContext context, int index) {
    //鏄剧ず澶撮儴4涓狢ell
    if (index < _headerData.length) {
      return _FriendCell(
        imageAssets: _headerData[index].imageAssets,
        name: _headerData[index].name,
      );
    }
    //鏄惁鏄剧ず缁勫悕瀛楋紒
    bool _hiddenIndexLetter = (index - 4 > 0 &&
        _listDatas[index - 4].indexLetter == _listDatas[index - 5].indexLetter);

    return _FriendCell(
      imageUrl: _listDatas[index - 4].imageUrl,
      name: _listDatas[index - 4].name,
      groupTitle: _hiddenIndexLetter null : _listDatas[index - 4].indexLetter,
    );
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
        appBar: AppBar(
          backgroundColor: logic.WeChatThemeColor,
          title: Text('閫氳褰?),
        ),
        body: Stack(
          children: [
            Container(
              color: logic.WeChatThemeColor,
              child: ListView.builder(
                controller: _scrollController,
                itemBuilder: _itemForRow,
                itemCount: _listDatas.length + _headerData.length,
              ),
            ), //鍒楄〃
            logic.IndexBar(
              indexBarCallBack: (String str) {
                if (_groupOffsetMap[str] != null) {
                  _scrollController.animateTo(_groupOffsetMap[str],
                      duration: Duration(microseconds: 100),
                      curve: Curves.easeIn);
                }
              },
            ), //鎮诞鐨勭储寮曟潯
          ],
        ));
  }
}

class Friends {
  Friends({this.imageUrl, this.name, this.indexLetter, this.imageAssets});
  final StringimageAssets;
  final StringimageUrl;
  final Stringname;
  final StringindexLetter;
}

List<Friends> datas = [
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/27.jpg',
      name: 'Lina',
      indexLetter: 'L'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/17.jpg',
      name: '鑿插効',
      indexLetter: 'F'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/16.jpg',
      name: '瀹夎帀',
      indexLetter: 'A'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/men/31.jpg',
      name: '闃胯吹',
      indexLetter: 'A'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/22.jpg',
      name: '璐濇媺',
      indexLetter: 'B'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/37.jpg',
      name: 'Lina',
      indexLetter: 'L'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/18.jpg',
      name: 'Nancy',
      indexLetter: 'N'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/men/47.jpg',
      name: '鎵f墸',
      indexLetter: 'K'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/men/3.jpg',
      name: 'Jack',
      indexLetter: 'J'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/5.jpg',
      name: 'Emma',
      indexLetter: 'E'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/24.jpg',
      name: 'Abby',
      indexLetter: 'A'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/men/15.jpg',
      name: 'Betty',
      indexLetter: 'B'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/men/13.jpg',
      name: 'Tony',
      indexLetter: 'T'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/men/26.jpg',
      name: 'Jerry',
      indexLetter: 'J'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/men/36.jpg',
      name: 'Colin',
      indexLetter: 'C'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/12.jpg',
      name: 'Haha',
      indexLetter: 'H'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/11.jpg',
      name: 'Ketty',
      indexLetter: 'K'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/13.jpg',
      name: 'Lina',
      indexLetter: 'L'),
  Friends(
      imageUrl: 'https://randomuser.me/api/portraits/women/23.jpg',
      name: 'Lina',
      indexLetter: 'L'),
];
  • 鐢变簬package_example宸ョ▼娌℃湁閰嶇疆assets瀵艰嚧椤甸潰鍥剧墖鍔犺浇涓嶅嚭鏉?/li>
插件开发与热重载原理,第26张
  • 鎴戜滑涓嶉厤缃?code>package_example宸ョ▼鐨?code>pubspec.yaml鏂囦欢锛屾垜浠紭鍖?code>logic_package_demo搴?/li>
// image涓巌con閮借缃垚鍙€夌殑
class IndexBar extends StatefulWidget {
  final void Function(String str) indexBarCallBack;
  final ImageProviderimage;
  final Iconicon;
  const IndexBar(
      {required this.indexBarCallBack, this.image, this.icon, Keykey})
      : super(key: key);
......

alignment: const Alignment(-0.2, 0),
children: [
  // 浼爄con灏辨樉绀篿con锛屼紶image灏辨樉绀篿mage锛岄兘涓嶄紶鐨勮瘽鏄剧ず閾哄簳鍥剧墖
  widget.icon 
    Image(
      image: widget.image 
      const AssetImage('images/bubble.png',
                                    package: 'logic_package_demo'),
       width: 60,
    ),
    Text(
      _indicatorText,
      style: 
          const TextStyle(fontSize: 35, color: Colors.white),
    )
],
  • package_example宸ョ▼閲嶆柊Pub get瀵煎叆logic_package_demo搴?/li>
  • package_example宸ョ▼鍒犻櫎涓嬪浘涓皵娉″浘鐗?/code>杩涜娴嬭瘯
插件开发与热重载原理,第27张
  • pubspec.yaml鏂囦欢杩涜閰嶇疆锛岄噸鏂拌繍琛屽伐绋?/li>
插件开发与热重载原理,第28张
  • 杩欎釜鏃跺€?code>閫氳褰曢〉闈?/code>澶撮儴鐨?code>Cell鍥炬爣杩樻病鏈夋樉绀哄嚭鏉ワ紝鎴戜滑淇敼package_example宸ョ▼鐨?code>main.dart鏂囦欢
插件开发与热重载原理,第29张
class _FriendCell extends StatelessWidget {
......

Container(
  margin: EdgeInsets.all(10),
  width: 34,
  height: 34,
  decoration: BoxDecoration(
    borderRadius: BorderRadius.circular(6.0),
    image: DecorationImage(
      image: imageUrl != null
      NetworkImage(imageUrl!)
      // 鏈湴鍥剧墖鎸囧畾鍒發ogic_package_demo鍖?
      : AssetImage(imageAssets!,
                              package: 'logic_package_demo') as ImageProvider,
  )),
), //鍥剧墖
插件开发与热重载原理,第30张
pubspec.yaml鏂囦欢閰嶇疆鍥剧墖骞惰繍琛宲ackage_example宸ョ▼
  • 鎶婄ず渚嬩唬鐮佸鍏?code>logic_package_demo宸ョ▼锛岄噸鏂板彂甯?code>Package鍖?/li>
插件开发与热重载原理,第31张

logic_package_demo宸ョ▼鏂板缓example鐩綍锛屾妸package_example绀轰緥宸ョ▼涓殑main.dart鏂囦欢瀵煎叆銆?/p>

  • logic_package_demo.dart鏂囦欢涓唬鐮佸お澶氾紝鎴戜滑杩涜鎷嗗垎瀵瑰簱杩涜浼樺寲
    鏂板缓index_bar.dart鏂囦欢锛屾妸logic_package_demo.dart鏂囦欢涓唬鐮佹娊鍙栧嚭鏉?/li>
<!-- logic_package_demo.dart鏂囦欢 -->
library logic_package_demo;
// 搴撲腑瀵煎叆鍗冲彲
import 'package:flutter/material.dart';
part 'index_bar.dart';

<!-- index_bar.dart鏂囦欢 -->
// 鎸囧畾灞炰簬鍝釜搴?
part of 'logic_package_demo.dart';

class IndexBar extends StatefulWidget {
  final void Function(String str) indexBarCallBack;
  final ImageProviderimage;
  final Iconicon;
  const IndexBar(
      {required this.indexBarCallBack, this.image, this.icon, Keykey})
      : super(key: key);

  @override
  _IndexBarState createState() => _IndexBarState();
}

//鑾峰彇閫変腑鐨処tem鐨勫瓧绗︼紒锛?
int getIndex(BuildContext context, Offset globalPosition) {
  //鎷垮埌鐐瑰墠灏忛儴浠剁殑鐩掑瓙
  RenderBox box = context.findRenderObject() as RenderBox;
  //鎷垮埌y鍊硷紝globalToLocal褰撳墠浣嶇疆鎴戦儴浠剁殑鍘熺偣(灏忛儴浠跺乏涓婅)鐨勮窛绂伙紙x,y锛?
  double y = box.globalToLocal(globalPosition).dy;
  //绠楀嚭瀛楃楂樺害
  var itemHeight = screenHeight(context) / 2 / INDEX_WORDS.length;
  //绠楀嚭绗嚑涓猧tem
  int index = (y ~/ itemHeight).clamp(0, INDEX_WORDS.length - 1);
  return index;
}

class _IndexBarState extends State<IndexBar> {
  Color _bkColor = Color.fromRGBO(1, 1, 1, 0.0);
  Color _textColor = Colors.black;
  double _indicatorY = 0.0;
  String _indicatorText = 'A';
  bool _indicatorHidden = true;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final List<Widget> words = [];
    for (int i = 0; i < INDEX_WORDS.length; i++) {
      words.add(Expanded(
          child: Text(
        INDEX_WORDS[i],
        style: TextStyle(fontSize: 10, color: _textColor),
      )));
    }
    return Positioned(
      right: 0.0,
      top: screenHeight(context) / 8,
      height: screenHeight(context) / 2,
      width: 120,
      child: Row(
        children: [
          Container(
            alignment: Alignment(0, _indicatorY),
            width: 100,
            // color: Colors.red,
            child: _indicatorHidden
                null
                : Stack(
                    alignment: const Alignment(-0.2, 0),
                    children: [
                      widget.icon 
                          Image(
                            image: widget.image 
                                const AssetImage('images/bubble.png',
                                    package: 'logic_package_demo'),
                            width: 60,
                          ),
                      Text(
                        _indicatorText,
                        style:
                            const TextStyle(fontSize: 35, color: Colors.white),
                      )
                    ],
                  ),
          ), //鎸囩ず鍣?
          GestureDetector(
            onVerticalDragUpdate: (DragUpdateDetails details) {
              int index = getIndex(context, details.globalPosition);
              widget.indexBarCallBack(INDEX_WORDS[index]);
              setState(() {
                _indicatorY = 2.2 / INDEX_WORDS.length * index - 1.1;
                _indicatorText = INDEX_WORDS[index];
                _indicatorHidden = false;
              });
            },
            onVerticalDragDown: (DragDownDetails details) {
              int index = getIndex(context, details.globalPosition);
              widget.indexBarCallBack(INDEX_WORDS[index]);
              setState(() {
                _indicatorY = 2.2 / INDEX_WORDS.length * index - 1.1;
                _indicatorText = INDEX_WORDS[index];
                _indicatorHidden = false;
                _bkColor = Color.fromRGBO(1, 1, 1, 0.5);
                _textColor = Colors.white;
              });
            },
            onVerticalDragEnd: (DragEndDetails details) {
              setState(() {
                _indicatorHidden = true;
                _bkColor = Color.fromRGBO(1, 1, 1, 0.0);
                _textColor = Colors.black;
              });
            },
            child: Container(
              width: 20,
              color: _bkColor,
              child: Column(
                children: words,
              ),
            ),
          ), //绱㈠紩鏉?
        ],
      ),
    );
  }
}

//涓婚鑹?
const Color WeChatThemeColor = Color.fromRGBO(220, 220, 220, 1.0);

//灞忓箷瀹介珮
double screenWidth(BuildContext context) => MediaQuery.of(context).size.width;

double screenHeight(BuildContext context) => MediaQuery.of(context).size.height;

const INDEX_WORDS = [
  '馃攳',
  '鈽?,
  'A',
  'B',
  'C',
  'D',
  'E',
  'F',
  'G',
  'H',
  'I',
  'J',
  'K',
  'L',
  'M',
  'N',
  'O',
  'P',
  'Q',
  'R',
  'S',
  'T',
  'U',
  'V',
  'W',
  'X',
  'Y',
  'Z'
];
  • 鏇存敼pubspec.yaml鏂囦欢涓?code>CHANGELOG.md鏂囦欢涓殑鐗堟湰鍙蜂负1.0.0锛岀劧鍚庢墽琛?code>鍙戝竷鍛戒护
插件开发与热重载原理,第32张
pub.dev缃戠珯鏌ョ湅

plugin寮€鍙?/h2>

鏂板缓logic_plugin_demo宸ョ▼

插件开发与热重载原理,第33张
鏂板缓Plugin宸ョ▼

鏌ョ湅鎻掍欢宸ョ▼鐩綍锛岃嚜甯?code>example绀轰緥鐩綍锛屽叾涓?code>ios銆?code>android鐩綍涓嬪苟涓嶅寘鍚伐绋嬶紝鍙槸鍚勪釜骞冲彴鐨勪唬鐮?/p>

插件开发与热重载原理,第34张
鏌ョ湅鎻掍欢鐩綍

pubspec.yaml鏂囦欢閰嶇疆homepage

插件开发与热重载原理,第35张
homepage閰嶇疆

Plugin鎻掍欢寮€鍙?/h6>
  • logic_plugin_demo.dart鏂囦欢缂栧啓浠g爜濡備笅
import 'dart:async';

import 'package:flutter/services.dart';

class LogicPluginDemo {
  static const MethodChannel _channel =
      const MethodChannel('logic_plugin_demo');

  static Future<String?> get platformVersion async {
    final Stringversion = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }
  // 鑾峰彇鐢垫睜鐢甸噺
  static Future<String?> get platformBatteryLevel async {
    int batteryLevel = await _channel.invokeMethod('getPlatformBatteryLevel');
    return batteryLevel.toString();
  }
}
  • ios/Classes鐩綍涓嬬殑LogicPluginDemoPlugin.m鏂囦欢淇敼浠g爜濡備笅锛屼互鎺ユ敹Flutter鍙戦€佽繃鏉ョ殑娑堟伅
#import "LogicPluginDemoPlugin.h"

@implementation LogicPluginDemoPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  FlutterMethodChannel* channel = [FlutterMethodChannel
      methodChannelWithName:@"logic_plugin_demo"
            binaryMessenger:[registrar messenger]];
  LogicPluginDemoPlugin* instance = [[LogicPluginDemoPlugin alloc] init];
  [registrar addMethodCallDelegate:instance channel:channel];
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
  if ([@"getPlatformVersion" isEqualToString:call.method]) {
    result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
  // 鎺ユ敹Flutter鍙戦€佽繃鏉ョ殑鑾峰彇鐢垫睜鐢甸噺娑堟伅
  } else if([@"getPlatformBatteryLevel" isEqualToString:call.method]){
      int batteryLevel = [self getBatteryLevel];
      // 鎶婂€煎寘瑁呮垚瀵硅薄杩斿洖鍑哄幓
      result(@(batteryLevel));
  }else{
    result(FlutterMethodNotImplemented);
  }
}

-(int)getBatteryLevel{
    UIDevice * device = UIDevice.currentDevice;
    device.batteryMonitoringEnabled = YES;
    if (device.batteryLevel == UIDeviceOrientationUnknown) {
        return  -1;
    }else{
        return (int)(device.batteryState * 100);
    }
}

@end
  • 涓婇潰浠g爜缂栧啓瀹屾垚涔嬪悗锛屽湪example/lib/main.dart鏂囦欢涓繘琛岃皟璇?/li>
插件开发与热重载原理,第36张
鑾峰彇鐢垫睜鐢甸噺
  • 鎵撳紑example/ios鐩綍涓嬬殑Runner宸ョ▼锛屼娇鐢ㄧ湡鏈烘煡鐪嬭幏鍙栫數閲忔儏鍐?/li>
插件开发与热重载原理,第37张
鑾峰彇鍒板綋鍓嶈澶囩數閲忔槸婊$殑
  • logic_plugin_demo鎻掍欢杩涜鍙戝竷
// 妫€鏌lugin鍖?
$ flutter packages pub publish --dry-run
// 鎸囧畾鏈嶅姟鍣ㄥ彂甯?
$ flutter packages pub publish --server=https://pub.dartlang.org

Plugin鎻掍欢鐨勫彂甯冧笌Package鍖呯殑鍙戝竷鏄竴鏍风殑锛?code>娉ㄦ剰閰嶇疆璇佷功锛堝悓涓婏級銆?/p>

鐑噸杞芥寕杞?/h2>
插件开发与热重载原理,第38张
鐑噸杞界殑鏈湴Server鏈嶅姟鍣?/div>
鐑噸杞藉垵鎺?/h6>

Flutter鏄竴濂楀叏鏂扮殑璺ㄥ钩鍙版柟妗堬紝Flutter骞朵笉鍍?code>React Native閭f牱渚濊禆鍘熺敓搴旂敤鐨勬覆鏌擄紝鑰屾槸鑷繁鏈変竴濂楁覆鏌撳紩鎿庯紝骞朵娇鐢?code>Dart褰撲綔Flutter鐨勫紑鍙戣瑷€銆?code>Flutter鏁翠綋妗嗘灦鍒嗕负涓ゅ眰锛屽簳灞傛槸閫氳繃C++瀹炵幇鐨勫紩鎿庨儴鍒嗭紝Skia鏄?code>Flutter鐨勬覆鏌撳紩鎿庯紝璐熻矗璺ㄥ钩鍙扮殑鍥惧舰娓叉煋銆?code>Dart浣滀负Flutter鐨勫紑鍙戣瑷€锛屽湪C++寮曟搸涓婂眰鏄?code>Dart鐨?code>Framework銆?/p>

Flutter鏀寔浜氱绾х儹閲嶈浇锛?code>Android Studio鍜?code>VSCode閮芥敮鎸?code>Hot Reload鐨勭壒鎬э紱浣嗛渶瑕佸尯鍒嗙殑鏄?code>鐑噸杞藉拰鐑洿鏂版槸涓や釜涓嶅悓鐨勬蹇?/code>

  • 鐑噸杞?/code>鏄湪杩愯璋冭瘯鐘舵€佷笅锛屽皢鏂颁唬鐮佺洿鎺ユ洿鏂板埌鎵ц涓殑浜岃繘鍒?/li>
  • 鐑洿鏂?/code>鏄湪涓婄嚎鍚庯紝閫氳繃Runtime鎴栧叾浠栨柟寮忥紝鏀瑰彉鐜版湁鎵ц閫昏緫

鐑噸杞界殑鎼缓鏄彲浠ュ仛鍒扮儹鏇存柊鐨?/code>

AOT 銆丣IT

Flutter鏀寔AOT锛圓head of time锛夊拰JIT锛圝ust in time锛変袱绉嶇紪璇戞ā寮?/p>

  • JIT妯″紡鏀寔鍦ㄨ繍琛岃繃绋嬩腑杩涜Hot Reload锛屽埛鏂拌繃绋嬫槸涓€涓閲忕殑杩囩▼锛岀敱绯荤粺瀵规湰娆″拰涓婃鐨勪唬鐮佸仛涓€娆?code>snapshot锛屽皢鏂扮殑浠g爜娉ㄥ叆鍒?code>DartVM涓繘琛屽埛鏂帮紝浣嗘湁鏃朵細涓嶈兘杩涜Hot Reload锛屾鏃惰繘琛屼竴娆″叏閲忕殑Hot Reload鍗冲彲
  • AOT妯″紡鍒欐槸鍦ㄨ繍琛屽墠棰勫厛缂栬瘧濂斤紝杩欐牱鍦ㄦ瘡娆¤繍琛岃繃绋嬩腑灏变笉闇€瑕佽繘琛屽垎鏋愩€佺紪璇戙€佹妯″紡鐨勮繍琛岄€熷害鏄渶蹇殑銆?/li>

Flutter鍚屾椂閲囩敤浜嗕袱绉嶆柟妗堬紝鍦ㄥ紑鍙戦樁娈甸噰鐢?code>JIT妯″紡杩涜寮€鍙戯紱鍦?code>release闃舵閲囩敤AOT妯″紡锛屽皢浠g爜鎵撳寘涓轰簩杩涘埗杩涜鍙戝竷銆?/p>

鍦ㄥ紑鍙戝師鐢熷簲鐢ㄦ椂锛屾瘡娆′慨鏀逛唬鐮佸悗閮介渶瑕侀噸鏂扮紪璇戯紝鑰屼笖杩愯鍒扮‖浠惰澶囦笂锛涚敱浜?code>Flutter鏀寔Hot Reload锛屽彲浠ヨ繘琛岀儹閲嶈浇锛屽椤圭洰鐨勫紑鍙戞晥鐜囨湁寰堝ぇ鐨勬彁鍗囥€?/p>

鐢变簬Flutter瀹炵幇鏈哄埗鏀寔JIT鐨勫師鍥狅紝鐞嗚涓婃潵璇存槸鏀寔鐑洿鏂颁互鍙婃湇鍔″櫒涓嬪彂浠g爜鐨勶紱浣嗘槸鐢变簬杩欐牱浼氫娇鎬ц兘鍙樺樊锛岃€屼笖杩樻湁瀹℃牳闂锛屾墍浠?code>Flutter娌℃湁閲囩敤杩欑鏂规銆?/p>

鐑噸杞?/code>鏈川灏辨槸閫氳锛?code>server绔?/code>涓?code>Dart绔?/code>涔嬮棿杩涜閫氳锛屾帴鏀跺埌Dart绔?/code>鍙戠敓浜嗗彉鍖栵紝鏈嶅姟绔細鍛婅瘔Flutter.framework鍘昏繘琛屾覆鏌?/p>

  • 鏂板缓App绫诲瀷宸ョ▼hotload_demo
  • 灏?code>Server绔?/code>鎸傝浇鍒?code>hotload_demo宸ョ▼
  1. 杩涘叆~/flutter/packages/flutter_tools锛屾妸flutter_tools鐩綍鍐呭鐢?code>Android Studio鎵撳紑
插件开发与热重载原理,第39张
Flutter SDK鐩綍
  1. flutter_tools宸ョ▼灏辩浉褰撲簬server绔?/code>锛?code>hotload_demo宸ョ▼灏辩浉褰撲簬app绔?/code>锛?/li>
  2. flutter_tools娣诲姞Dart Command Line App
插件开发与热重载原理,第40张
娣诲姞Dart Command Line App
  1. 閫夋嫨鎸傝浇鐨勫伐绋嬶紝骞惰繍琛?/li>
插件开发与热重载原理,第41张
閰嶇疆鎸傝浇宸ョ▼
插件开发与热重载原理,第42张
閰嶇疆Program arguments
  • 閰嶇疆Dart SDK Path锛岄€夋嫨Android Studio -> Preferences...
插件开发与热重载原理,第43张
閰嶇疆Dart SDK Path
  • 杩愯flutter_tools宸ョ▼
插件开发与热重载原理,第44张

浠?code>server绔?/code>鍦ㄨ繍琛岋紝瀹為檯涓婃寕杞界殑鏄?code>hotload_demo宸ョ▼锛涗笅闈㈣繘琛岄獙璇?/p>

  1. 淇敼hotload_demo宸ョ▼椤甸潰title
插件开发与热重载原理,第45张
  1. 鎵ц杩愯鍛戒护鏌ョ湅title
插件开发与热重载原理,第46张
插件开发与热重载原理,第47张

瀹炵幇浜嗕笂闈㈢殑鐑噸杞芥寕杞?/code>锛屾垜浠氨鍙互鍦?code>flutter_tools.dart鏂囦欢涓坊鍔犳柇鐐硅皟璇?code>鐑噸杞界殑鍘熺悊銆?/p>


https://www.xamrdz.com/lan/5cd1994623.html

相关文章: