【问题标题】:How to get the page is not disposed如何获取页面未处理
【发布时间】:2020-09-07 00:45:31
【问题描述】:

我的应用程序有使用位置的地图页面

class _MapPageState extends State<MapPage> {
  LocationData currentLocation;  
  Location _locationService = new Location();   
  @override
  void initState(){
    super.initState();                                                
    _locationService.onLocationChanged().listen((LocationData result) async { 
      setState(() {       
        print(result.latitude);
        print(result.longitude);                                                  
        currentLocation = result;                                             
      });                                                                     
    });  
  }

在这种情况下,setState() 在显示地图时效果很好。

但是在mappage被处理之后,就会出现这样的错误。

E/flutter ( 6596): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter ( 6596): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.

所以,我有两个想法。

  1. 当页面被释放时移除onLocationChanged()监听器。

  2. 检查State是否在setState()之前被释放

我该如何解决这个问题??

【问题讨论】:

标签: flutter


【解决方案1】:

可以复制粘贴下面两个文件,直接替换官方示例代码
https://github.com/Lyokone/flutterlocation/tree/master/location/example/lib
NavigateListenLocationWidget 页面之后, 你可以打电话给_stopListen()dispose()

代码sn-p

class _MyHomePageState
...
   RaisedButton(
      child: Text('Open route'),
      onPressed: () {
        Navigator.push(
          context,
          MaterialPageRoute<void>(
              builder: (context) => ListenLocationWidget()),
        );
      },
    ),
    PermissionStatusWidget(),
    Divider(height: 32),
    ServiceEnabledWidget(),
    Divider(height: 32),
    GetLocationWidget(),
    Divider(height: 32),
    //ListenLocationWidget()


class _ListenLocationState extends State<ListenLocationWidget> {
...
StreamSubscription<LocationData> _locationSubscription;
  String _error;

  @override
  void initState() {
    print("initState");
    super.initState();
    _listenLocation();
  }

  @override
  void dispose() {
    print("stopListen");
    _stopListen();
    super.dispose();
  }
  
  Future<void> _listenLocation() async {
    _locationSubscription =
        location.onLocationChanged.handleError((dynamic err) {
      setState(() {
        _error = err.code;
      });
      _locationSubscription.cancel();
    }).listen((LocationData currentLocation) {
      setState(() {
        print("setState");
        _error = null;

        _location = currentLocation;
      });
    });
  }

  Future<void> _stopListen() async {
    _locationSubscription.cancel();
  }

工作演示

完整代码ListenLocationWidget

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:location/location.dart';

class ListenLocationWidget extends StatefulWidget {
  const ListenLocationWidget({Key key}) : super(key: key);

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

class _ListenLocationState extends State<ListenLocationWidget> {
  final Location location = Location();

  LocationData _location;
  StreamSubscription<LocationData> _locationSubscription;
  String _error;

  @override
  void initState() {
    print("initState");
    super.initState();
    _listenLocation();
  }

  @override
  void dispose() {
    print("stopListen");
    _stopListen();
    super.dispose();
  }
  
  Future<void> _listenLocation() async {
    _locationSubscription =
        location.onLocationChanged.handleError((dynamic err) {
      setState(() {
        _error = err.code;
      });
      _locationSubscription.cancel();
    }).listen((LocationData currentLocation) {
      setState(() {
        print("setState");
        _error = null;

        _location = currentLocation;
      });
    });
  }

  Future<void> _stopListen() async {
    _locationSubscription.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Container(
        color: Colors.white,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(
              'Listen location: ' + (_error ?? '${_location ?? "unknown"}'),
              style: Theme.of(context).textTheme.body2,
            ),
            Row(
              children: <Widget>[
                Container(
                  margin: const EdgeInsets.only(right: 42),
                  child: RaisedButton(
                    child: const Text('Listen'),
                    onPressed: _listenLocation,
                  ),
                ),
                RaisedButton(
                  child: const Text('Stop'),
                  onPressed: _stopListen,
                )
              ],
            ),
          ],
        ),
      ),
    );
  }
}

完整代码main.dart

import 'package:flutter/material.dart';
import 'package:location/location.dart';
import 'package:url_launcher/url_launcher.dart';

import 'get_location.dart';
import 'listen_location.dart';
import 'permission_status.dart';
import 'service_enabled.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Location',
      theme: ThemeData(
        primarySwatch: Colors.amber,
      ),
      home: const MyHomePage(title: 'Flutter Location Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  final Location location = Location();

  Future<void> _showInfoDialog() {
    return showDialog<void>(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('Demo Application'),
          content: SingleChildScrollView(
            child: ListBody(
              children: <Widget>[
                const Text('Created by Guillaume Bernos'),
                InkWell(
                  child: Text(
                    'https://github.com/Lyokone/flutterlocation',
                    style: TextStyle(
                      decoration: TextDecoration.underline,
                    ),
                  ),
                  onTap: () =>
                      launch('https://github.com/Lyokone/flutterlocation'),
                ),
              ],
            ),
          ),
          actions: <Widget>[
            FlatButton(
              child: const Text('Ok'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.info_outline),
            onPressed: _showInfoDialog,
          )
        ],
      ),
      body: Container(
        padding: const EdgeInsets.all(32),
        child: Column(
          children: <Widget>[
            RaisedButton(
              child: Text('Open route'),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute<void>(
                      builder: (context) => ListenLocationWidget()),
                );
              },
            ),
            PermissionStatusWidget(),
            Divider(height: 32),
            ServiceEnabledWidget(),
            Divider(height: 32),
            GetLocationWidget(),
            Divider(height: 32),
            //ListenLocationWidget()
          ],
        ),
      ),
    );
  }
}

【讨论】:

  • 非常感谢。我测试了工作演示。我从大参考您的代码开始。
猜你喜欢
  • 1970-01-01
  • 2013-04-13
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 2012-02-16
相关资源
最近更新 更多