在Flutter中等效于viewWillAppear()

时间:2019-06-09 02:27:57

标签: ios flutter dart

我正在使用Flutter重建iOS应用,流程如下: 每次用户登陆首页时,都会从后端重新加载用户数据,以检查是否有任何更改。

我在Swift / iOS中实现此目标的方法是使用viewDidLoad()函数。

我的Flutter代码如下:

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  User user = User();

  @override
  void dispose() {
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    _fetchData(context);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        color: RColor.COLOR_main,
        child: Column(
          children: [
            Container(
              height: MediaQuery.of(context).size.height / 7,
              width: MediaQuery.of(context).size.width,
              padding: EdgeInsets.all(20),
              child: Container(
                child: Text("This is the homepage"),
                alignment: Alignment.bottomCenter,
              ),
            ),
          ],
        ));
  }

  Future _fetchData(BuildContext context) async {
    _fetchUserAPI(context);
  }

  Future _fetchUserAPI(BuildContext context) async {
    try {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      var accessToken = prefs.getString("access_token");
      var url = RConstants.API_BASE_URL + "/v1/users/self";
      Response response = await Dio()
          .get(url, options: Options(headers: {"Authorization": accessToken}));
      setState(() {
        user = User.fromJson(response.data);
      });
    } catch (e) {
      print(e.toString());
      Alert(
              context: context,
              title: "Something Went Wrong",
              desc: "Something went wrong while fetching your user data",
              type: AlertType.error)
          .show();
    }
  }
}

void initState()不会在用户每次登陆首页时触发。实现此目的的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

好吧,这实际上取决于Everytime the user lands on the homepage的确切含义。 如果用户通过HomePageNavigator.push导航到其他视图,然后通过Navigator.pop返回,则HomePage的状态保持不变,当然{{1 }}方法不会触发。

如果要在initState上获得通知,如果导航器中位于其上方的路由弹出,则需要使用this方法,对其进行覆盖,然后在其中调用HomePage并更新首页的状态。

另一件事:当您进行诸如_fetchData()之类的异步调用时,仅在_fetchData()或任何其他框架方法中调用它是错误的模式。因为它将被调用,并且状态的initState()方法几乎总是在异步调用的结果返回之前立即被调用。处理此类情况的正确方法是使用FutureBuilder小部件。

build()表示其他含义时,例如该应用程序处于后台并成为前台,或者当支持实施推送通知并且用户单击通知并打开该应用程序时-此类情况也可以处理,但这是更广泛的主题。

答案 1 :(得分:0)

RouteAware 可以提供帮助。

  1. 在 main.dart 中定义 final RouteObserver<ModalRoute<void>> routeObserver = RouteObserver<ModalRoute<void>>();
  2. 在 MaterialApp 函数中设置 navigatorObservers: <RouteObserver<ModalRoute<void>>>[ routeObserver ],
  3. 在需要实现 RouteAware 功能的页面中混入 viewWillAppear
  4. 覆盖 didChangeDependenciesdidPopNext 方法并将此页面订阅到 routeObserver

例如:

main.dart

final RouteObserver<ModalRoute<void>> routeObserver = RouteObserver<ModalRoute<void>>();
void main() {
    runApp(MaterialApp(
        home: HomePage(),
        navigatorObservers: <RouteObserver<ModalRoute<void>>>[ routeObserver ],
    ));
}

home_page.dart

class _HomePageState extends State<HomePage> with RouteAware {
    @override
    void didChangeDependencies() {
        super.didChangeDependencies();
        routeObserver.subscribe(this, ModalRoute.of(context)!);
    }

    @override
    void dispose() {
        routeObserver.unsubscribe(this);
        super.dispose();
    }

    @override
    void didPopNext() {
        super.didPopNext();
        debugPrint("viewWillAppear");
    }
}