Flutter: Chạy phương pháp trên bản dựng Widget hoàn chỉnh


125

Tôi muốn có thể chạy các chức năng sau khi một Widget đã hoàn thành việc xây dựng / tải nhưng tôi không chắc về cách thức. Trường hợp sử dụng hiện tại của tôi là kiểm tra xem người dùng có được xác thực hay không và nếu không, hãy chuyển hướng đến chế độ xem đăng nhập. Tôi không muốn kiểm tra trước và đẩy chế độ xem đăng nhập hoặc chế độ xem chính, nó cần phải xảy ra sau khi chế độ xem chính đã tải. Có bất cứ điều gì tôi có thể sử dụng để làm điều này?


Không chắc rằng bạn muốn bắt đầu quá trình đăng nhập build. Xây dựng có thể được gọi bất kỳ lúc nào nhiều lần.
Günter Zöchbauer

Câu trả lời:


182

Bạn đã có thể sử dụng

https://github.com/slightfoot/flutter_ after_layout

thực thi một chức năng chỉ một lần sau khi hoàn thành bố cục. Hoặc chỉ cần xem triển khai của nó và thêm nó vào mã của bạn :-)

Về cơ bản là

  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => yourFunction(context));
  }

Cảm ơn @thomas ans của bạn rất hữu ích cho tôi. tôi làm việc này trước hai ngày và bây giờ họ và sau khi đọc ans của bạn. một lần nữa cảm ơn bạn công việc tốt rất mush
Ravindra Bhanderi

6
Xem câu trả lời của @ anmol.majhail: WidgetsBinding.instance.addPostFrameCallback((_) => yourFunciton(context));không còn hoạt động
Pablo Insua

Xin chào @Thomas, nó không hoạt động với tôi. vẫn nhận được ngoại lệ null. bất kỳ ý tưởng ?
zukijuki

1
@anunixercoder: nó phụ thuộc vào trường hợp sử dụng của bạn. Đôi khi, bạn nên gọi nó bằng cách khác initState, ví dụ. trong build.
Giraldi

2
bạn nên gọi setStatetrong yourFunctionphương pháp để làm cho nó làm việc
Pars

89

CẬP NHẬT: Flutter v1.8.4

Cả hai mã được đề cập hiện đang hoạt động:

Đang làm việc:

WidgetsBinding.instance
        .addPostFrameCallback((_) => yourFunction(context));

Đang làm việc

import 'package:flutter/scheduler.dart';

SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));

1
Cái thứ hai không còn hoạt động. NoSuchMethodError (NoSuchMethodError: The method 'addPostFrameCallback' was called on null. Receiver: null
Oliver Dixon

1
@EliaWeiss - nó Phụ thuộc vào trường hợp sử dụng của bạn - Đây chỉ là một cách để gọi một hàm trên Widget sau khi xây dựng. sử dụng điển hình sẽ được trong init ()
anmol.majhail

20

Có 3 cách khả thi:

1) WidgetsBinding.instance.addPostFrameCallback((_) => yourFunc(context));

2) Future.delayed(Duration.zero, () => yourFunc(context));

3) Timer.run(() => yourFunc(context));

Về phần context, tôi cần nó để sử dụng Scaffold.of(context)sau khi tất cả các widget của tôi được hiển thị.

Nhưng theo ý kiến ​​khiêm tốn của tôi, cách tốt nhất để làm điều đó là:

void main() async {
  WidgetsFlutterBinding.ensureInitialized(); //all widgets are rendered here
  await yourFunc();
  runApp( MyApp() );
}

13

Flutter 1.2 - phi tiêu 2.2

Theo các nguyên tắc và nguồn chính thức, nếu bạn muốn chắc chắn rằng khung cuối cùng của bố cục cũng được vẽ, bạn có thể viết ví dụ:

import 'package:flutter/scheduler.dart';

void initState() {
   super.initState();
   if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
        SchedulerBinding.instance.addPostFrameCallback((_) => yourFunction(context));
   }
}

Đối với tôi đây không làm việc, bởi vì tại initState () thời gian tôi nhận được schedulerPhase với SchedulerPhase.idle giá trị ... những gì nó thực sự làm việc là để thêm rằng séc trong xây dựng ()
Alessio

11

Nếu bạn đang tìm kiếm componentDidMounttương đương của ReactNative , Flutter có nó. Nó không đơn giản nhưng nó hoạt động theo cùng một cách. Trong Flutter, Widgets không xử lý trực tiếp các sự kiện của chúng. Thay vào đó họ sử dụng Stateđối tượng của mình để làm điều đó.

class MyWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => MyState(this);

  Widget build(BuildContext context){...} //build layout here

  void onLoad(BuildContext context){...} //callback when layout build done
}

class MyState extends State<MyWidget>{

  MyWidget widget;

  MyState(this.widget);

  @override
  Widget build(BuildContext context) => widget.build(context);

  @override
  void initState() => widget.onLoad(context);
}

State.initStatengay lập tức sẽ được gọi khi màn hình kết thúc việc hiển thị bố cục. Và sẽ không bao giờ được gọi lại ngay cả khi tải lại nóng nếu bạn đang ở chế độ gỡ lỗi, cho đến khi đạt đến thời gian rõ ràng để làm như vậy.


Từ ví dụ của tôi, bạn có thể sử dụng StatefulWidgetlớp để xử lý Stateđối tượng của nó giống như một đối tượng StatelessWidgetnhưng tôi thực sự không khuyến khích nó. Tôi vẫn chưa tìm thấy bất kỳ vấn đề nào nhưng hãy cố gắng triển khai mọi thứ bên trong Stateđối tượng trước
jerinho.com 27/02/19

2
flashing.dev/docs/cookbook/networking/fetch-data Google khuyên bạn nên gọi tìm nạp dữ liệu trên initState (). Do đó, không có vấn đề gì với giải pháp này, trên thực tế đây phải là câu trả lời được chấp nhận.
Nhà phát triển

Trong React Native, có thể thực hiện tìm nạp dữ liệu componentWillMountngay trước khi hiển thị bố cục. Flutter cung cấp giải pháp đơn giản hơn. initStatelà đủ cho cả dữ liệu quyến rũ và bố trí trả lại nếu chúng ta biết làm thế nào để làm việc đó đúng
jerinho.com

1
componentWillMount sẽ sớm ngừng hoạt động. Do đó, việc tìm nạp sẽ được thực hiện sau khi thành phần đã được gắn kết và xây dựng.
Nhà phát triển

8

Trong phiên bản Flagship 1.14.6, phiên bản Dart 28.

Dưới đây là những gì phù hợp với tôi, Bạn chỉ cần gói mọi thứ bạn muốn xảy ra sau phương thức xây dựng thành một phương thức hoặc hàm riêng biệt.

@override
void initState() {
super.initState();
print('hello girl');

WidgetsBinding.instance
    .addPostFrameCallback((_) => afterLayoutWidgetBuild());

}

3

Hãy thử Lập lịch biểuBinding,

 SchedulerBinding.instance
                .addPostFrameCallback((_) => setState(() {
              isDataFetched = true;
            }));

1

Cách tốt nhất để làm điều này,

1. WidgetBinding

WidgetsBinding.instance.addPostFrameCallback((_) {
      print("WidgetsBinding");
    });

2. WidgetBinding

SchedulerBinding.instance.addPostFrameCallback((_) {
  print("SchedulerBinding");
});

Nó có thể được gọi bên trong initState, cả hai sẽ chỉ được gọi một lần sau khi Xây dựng các vật dụng hoàn tất với việc kết xuất.

@override
  void initState() {
    // TODO: implement initState
    super.initState();
    print("initState");
    WidgetsBinding.instance.addPostFrameCallback((_) {
      print("WidgetsBinding");
    });
    SchedulerBinding.instance.addPostFrameCallback((_) {
      print("SchedulerBinding");
    });
  }

cả hai mã trên sẽ hoạt động giống nhau vì cả hai đều sử dụng khuôn khổ ràng buộc tương tự. Để có sự khác biệt, hãy tìm liên kết dưới đây.

https://medium.com/flutterworld/flutter-schedulerbinding-vs-widgetsbinding-149c71cb607f


0

Nếu bạn chỉ muốn thực hiện điều này một lần, thì hãy làm điều đó vì Khung công tác sẽ gọi initState()phương thức chính xác một lần cho mỗi đối tượng Trạng thái mà nó tạo ra.

 @override
  void initState() {
    super.initState();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => executeAfterBuildComplete(context));
  }

Nếu bạn muốn thực hiện điều này lặp đi lặp lại như quay lại hoặc điều hướng đến màn hình tiếp theo và v.v., hãy làm điều đó vì didChangeDependencies()Được gọi khi một phụ thuộc của đối tượng Trạng thái này thay đổi.

Ví dụ, nếu cuộc gọi trước đó buildtham chiếu đến một InheritedWidgetmà sau đó đã thay đổi, khung công tác sẽ gọi phương thức này để thông báo cho đối tượng này về sự thay đổi.

Phương thức này cũng được gọi ngay sau đó initState. Nó là an toàn để gọi BuildContext.dependOnInheritedWidgetOfExactTypetừ phương pháp này.

 @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    WidgetsBinding.instance
        .addPostFrameCallback((_) => executeAfterBuildComplete(context));
  }

Đây là chức năng Gọi lại của bạn

executeAfterBuildComplete([BuildContext context]){
    print("Build Process Complete");
  }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.