自學Flutter

137 回覆
70 Like 2 Dislike
2022-06-16 22:50:26
識react native再學react就易上手好多
睇你覺得學一樣獨立野定點
2022-06-16 23:05:37
2022-06-17 02:37:12
係咪調轉左
乜都唔識去學react native慘過死 d documentation屎一樣
javascript > typescript > react > react native 咩樣比較正路wo
2022-06-17 02:38:25
好似幾好玩
2022-06-17 12:14:06
2022-06-17 12:16:03
Lm
2022-06-17 12:17:52
2022-06-17 13:16:41
而家expo 四行cmd無痛set up
https://reactnative.dev/docs/environment-setup
2022-06-17 14:04:35
試下轉用gapstyle color scheme,好睇好多
2022-06-17 14:49:52
最緊要係揀岩 state management
有冇用過provider?
升級個分別係邊?
2022-06-17 15:05:21
好 我試試
2022-06-17 15:15:38
Architecture pattern嗰度對Flutter嚟講唔啱

Flutter已經有個opinion on Architecture pattern
所以冇MVC MVVM
應該寫BLoC or Hook 之類

個graph睇落去幾靚 作為一個總結唔錯
但Roadmap同學習次序冇咩關係

你試下轉貼我嘅comment(代 fd 覆樓主你)
2022-06-17 15:17:16
冇用過provider 但之前做過research
冇記錯的話最大分別應該係

provider
flutter dependent 需要context
會有run time error
如果你有幾個provider係同1個obeject type 你只能拎到最近嗰個

riverpod
唔需要context
compile-time safe
就算同1個type 你想拎邊個provider就拎邊個 因為riverpod入面provider係global variables
2022-06-17 15:27:00
其實用singleton +changeNotifier 都唔錯
2022-06-17 15:40:22
可唔可以講多少少
咁你個layer structure係點?
2022-06-17 15:49:04
另外想問下
我而家有一個list of items
同時我想support search功能 我而家做法係filter咗items先放落去ListView.builder

// providers
final filteredMovesProvider = StateProvider.autoDispose<List<Move>>((ref) {
  final searchText = ref.watch(searchTextProvider);
  final moves = ref.watch(movesProvider);
  if (searchText.isEmpty || searchText.trim().isEmpty) {
    return moves;
  } else {
    return moves
        .where((item) =>
            item.name.removeWhitespace().toLowerCase().contains(searchText.removeWhitespace().toLowerCase()) ||
            item.id.toString().contains(searchText))
        .toList();
  }
});

// MovePage
 final filteredList = ref.watch(filteredMovesProvider);
 return ListView.builder(
      itemCount: filteredList.length,
      itemBuilder: (context, index) {


但係有個情況就係當user scroll咗一陣個list先search
之後cancel search個list會去返最top而唔係原本位置



我暫時諗到嘅解決方法就係分開原本list同filtered list
Visibilitywidget 去控制show邊個list
未試 唔知work唔work
2022-06-17 17:09:01
Provider個度有d唔啱
你只要call context個位放得啱就唔會有runtime error
provider個concept應該只有一個instance存在 所以有幾個instance嘅provider只可以拎到最近個個問題 其實係用錯左
只要你將個provider係widget tree入面放得夠高 就可以當global variable咁用
Provider個煩位 係好wordy boilerplate code都唔少
不過聽講已經少過bloc

只係用過provider
2022-06-17 17:11:48
Declare ScrollController attach落listview到 再cache個scroll position
2022-06-17 17:21:19
Provider 要放岩位, 同埋hot reload 會有古怪問題

Selector又係玩到頭暈
用錯會update 唔到條list
2022-06-17 17:30:47
如果你有加減d variable hot reload一般都reload唔到 最後都係要全部reload一次
未用過selector
2022-06-17 17:35:36
RN 好在有code push
不過flutter 都有chimera 做code push, 不過未用過
同埋 rn 要eject都幾煩
2022-06-17 18:07:55
之前我哋move page用 RiverpodFutureProvider
如果你想有多啲control
可以轉用StateNotifierProvider
首先define 1個 StateNotifier
呢個StateNotifier嘅state可以係int, bool或者其他immutable type
下面嘅state就係List<Move>
當呢個state變嘅時候 其他有 watch呢個state嘅widget都會自動rebuild
呢個StateNotifier 可以define method去change state
fetchData() 就係用嚟download data

class MovesController extends StateNotifier<List<Move>> {
  MovesController({required IMoveRepository repository})
      : _repository = repository,
        super([]); // initial state: empty list

  final IMoveRepository _repository;

  Future<void> fetchData({int limit = 20, int offset = 0}) async {
    final moves = await _repository.fetchData(limit: limit, offset: offset);
    state = [...state, ...moves]; // change state
  }

  int get count => state.length;
}

// provider
final movesControllerProvider = StateNotifierProvider<MovesController, List<Move>>((ref) {
  final repository = ref.watch(moveRepositoryProvider);
  return MovesController(repository: repository);
});
2022-06-17 18:08:36
而家move page有一個button去call fetchData()
响button onPressed() callback 入面唔可以用 ref.watch()
要用ref.read() 同埋係read <yourStateNotifierProvider>.notifier

// move_page.dart
// inside build method
final moves = ref.watch(movesControllerProvider);

return Scaffold(
  body: moves.isEmpty
      ? Center(
          child: ElevatedButton(
            onPressed: () {
              ref.read(movesControllerProvider.notifier).fetchData();
            },
            child: const Text('Press to download data'),
          ),
        )
      : Column(
          children: [
            Expanded(
              child: ListView.builder(
                ...
              ),
            ),
            ElevatedButton(
              onPressed: () {
                final currentCount = ref.read(movesControllerProvider.notifier).count;
                ref.read(movesControllerProvider.notifier).fetchData(offset: currentCount);
              },
              child: const Text('Press to download more data'),
            ),
          ],
        ),
);
吹水台自選台熱 門最 新手機台時事台政事台World體育台娛樂台動漫台Apps台遊戲台影視台講故台健康台感情台家庭台潮流台美容台上班台財經台房屋台飲食台旅遊台學術台校園台汽車台音樂台創意台硬件台電器台攝影台玩具台寵物台軟件台活動台電訊台直播台站務台黑 洞