flutter友盟统计之界面统计

作者: 幸福的脚步2016 | 来源:发表于2020-08-25 17:17 被阅读0次

    2020.10.20日更新:

    最近发现了一种更好的方法,就是使用RouteAware监听路由,下面是实现代码

    初始化:

    RouteObserver需要申明为全局属性并作为参数传入MaterialApp中

    static final RouteObserver<PageRoute> routeObserver = RouteObserver();
    
    @override
     Widget build(BuildContext context) {
       return MaterialApp(
         navigatorObservers: [AppRoutesManager.routeObserver],
         ...
       );
     }
    

    使用

    abstract class BaseState<T extends StatefulWidget, E extends BaseViewModel> extends State<T> with RouteAware {
      String pageName;
      E viewModel;
      void initState() {
        super.initState();
      }
    
      @override
      void didChangeDependencies() {
        AppRoutesManager.routeObserver.subscribe(this, ModalRoute.of(context)); //订阅
        super.didChangeDependencies();
     print("didChangeDependencies: ${pageName}界面");
      }
    
      @override
      void didPush() {
        debugPrint("------> didPush-进入${pageName}");
        super.didPush();
      }
    
      @override
      void didPop() {
        debugPrint("------> didPop离开${pageName}");
        super.didPop();
      }
    
      @override
      void didPopNext() {
        debugPrint("------> didPopNext-进入${pageName}");
        super.didPopNext();
      }
    
      @override
      void didPushNext() {
        debugPrint("------> didPushNext-${pageName}进入下一个界面");
        super.didPushNext();
      }
    
      @override
      void dispose() {
        AppRoutesManager.routeObserver.unsubscribe(this); //取消订阅
        super.dispose();
    //    print("dispose 离开${pageName}界面");
        print("销毁${pageName}界面");
      }
    

    但是这个方法有一定的缺陷:
    1,AlertView,showGeneralDialog等弹出框里面push的路由没有办法监听,我的解决办法是是写一个回调函数来让主界面来处理路由的push;
    2,当使用PageView做界面切换时,监听也是不生效的,这个时候需要自己手动调用RouteAware里面的函数。

    下面是之前的实现方法:

    之前项目集成了友盟统计的功能,发现flutter界面统计无法实现,在iOS中我们可以通过Controller的生命周期中的viewWillAppear:来处理什么时候进入界面viewWillDisappear:来处理什么时候来开界面,离开界面的处理,flutter的组件虽然也有生命周期,但是它的生命周期不足以支持我们准确的统计,虽然我们可以用initState做进入的的逻辑,用dispose做离开的逻辑,但是initState 只有在组件第一次初始化的时候跳用,dispose只有在组件销毁的时候才会调用;当我们使用Navigator.push离开当前界面进入下一个界面时我们没有办法做处理,当然我们也可以选择在每一个push的地方做处理,但是这样就会出现大量的重复代码,显然不符合我们的初衷,经过思考我给出了下面这个方案:

    1,写一个基类BaseState继承自State,其中有一个参数pageName

    abstract class BaseState<T extends StatefulWidget> extends State {
      String pageName;
      void initState() {
        // TODO: implement initState
        super.initState();
        print("initState 进入${pageName}界面");
        FlutterBlUmpushPlugin.umengEnterViewWithName(pageName);
      }
    
     @override
      Widget build(BuildContext context) {
        return build(context);
      }
     @override
      void dispose() {
        // TODO: implement dispose
        super.dispose();
        print("dispose 离开${pageName}界面");
        print("销毁${pageName}界面");
        FlutterBlUmpushPlugin.umengOutViewWithName(pageName);
      }
    }
    

    2,实现一个push函数,做统一的界面跳转,利用Future的特性做界面的离开,进入逻辑处理:

     //跳转界面
      void push({Widget page, Function popCallback}) {
        print("push: 离开${pageName}界面");
       FlutterBlUmpushPlugin.umengOutViewWithName(pageName);
        Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {
          return page;
        })).then((data) {
          print("pop 进入${pageName}界面");
          FlutterBlUmpushPlugin.umengEnterViewWithName(pageName);
          if (popCallback != null) {
            popCallback(data);
          }
        });
      }
    
      //路由跳转
      void routerPush({String route, Function popCallback}) {
        print("routerPush: 离开${pageName}界面");
       FlutterBlUmpushPlugin.umengOutViewWithName(pageName);
        AppRoutesManager.router.navigateTo(context, route).then((data) {
          print("pop 进入${pageName}界面");
          FlutterBlUmpushPlugin.umengEnterViewWithName(pageName);
          if (popCallback != null) {
            popCallback(data);
          }
        });
      }
    

    使用:

    class MinePage extends StatefulWidget {
      @override
      _MinePageState createState() => _MinePageState();
    }
    
    class _MinePageState extends BaseState<MinePage> with AutomaticKeepAliveClientMixin {
      @override
      bool get wantKeepAlive => true;
    
      @override
      void initState() {
        // TODO: implement initState
        pageName = "个人中心";
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: CustomAppBar(
            title: pageName,
          ),
          body: GestureDetector(
            onTap: () {
              routerPush(route: AppRoutesManager.mall, popCallback: (data) {});
            },
            child: Container(
              color: Colors.red,
            ),
          ),
        );
      }
    }
    

    注:如果是安卓的话可以通过initState(), deactivate()加一个bool类型的参数处理,不知道为什么iOS端的deactivate()函数在push下一个界面的时候不调用。

    相关文章

      网友评论

        本文标题:flutter友盟统计之界面统计

        本文链接:https://www.haomeiwen.com/subject/qsezjktx.html