Flutter:考虑在 Internet 更改其状态时在“处置”期间取消任何活动工作

问题描述

当互联网关闭时,我收到以下消息。

import pygame

pygame.init()

WIDTH,HEIGHT = 750,500
WINDOW = pygame.display.set_mode((WIDTH,HEIGHT))   

pygame.display.set_caption("PONG")  

WINNER_FONT = pygame.font.SysFont('comicsans',100)

BLUE = (0,255)          
RED = (255,0)           
YELLOW = (255,255,0)     
WHITE = (255,255)     
BLACK = (0,0)           

class Paddle(pygame.sprite.Sprite):     
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)    
        self.image = pygame.Surface([10,75])
        self.image.fill(WHITE)
        self.rect = self.image.get_rect()   
        self.paddle_speed = 4          
        self.points = 0

class Ball(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([10,10])
        self.image.fill(YELLOW)
        self.rect = self.image.get_rect()
        self.speed = 2
        self.dx = 1    
        self.dy = 1

def init():
    global paddle1,paddle2,ball,all_sprites

    paddle1 = Paddle()
    paddle1.image.fill(BLUE)
    paddle1.rect.x = 25      
    paddle1.rect.y = 225     

    paddle2 = Paddle()
    paddle2.image.fill(RED)
    paddle2.rect.x = 715
    paddle2.rect.y = 225

    ball = Ball()
    ball.rect.x = 375
    ball.rect.y = 250

    all_sprites = pygame.sprite.Group() 
    all_sprites.add(paddle1,ball)

def redraw():
    WINDOW.fill(BLACK)
    font = pygame.font.SysFont("Consolas",35)
    text = font.render("---[PONG]---",1,YELLOW)
    textRect = text.get_rect()      
    textRect.center = (WIDTH//2,25)  
    WINDOW.blit(text,textRect)     

    #Player 1 score
    p1_score = font.render(str([paddle1.points]),WHITE)
    p1Rect = p1_score.get_rect()    
    p1Rect.center = (50,50)        
    WINDOW.blit(p1_score,p1Rect)   
    
    #Player 2 score
    p2_score = font.render(str([paddle2.points]),WHITE)
    p2Rect = p2_score.get_rect()
    p2Rect.center = (700,50)      
    WINDOW.blit(p2_score,p2Rect)
    
    all_sprites.draw(WINDOW)    
    pygame.display.update()     


def draw_winner(text): 
    draw_text = WINNER_FONT.render(text,WHITE)
    WINDOW.blit(draw_text,(WIDTH//2 - draw_text.get_width()/2,HEIGHT//2 - draw_text.get_height()/2))
    pygame.display.update()


def main():
    init()
  
    winner_text = ""
    restart_time = 0
    game_over = False

    clock = pygame.time.Clock()
    run = True
    while run:
        clock.tick(100)
        current_time = pygame.time.get_ticks()
       
        for event in pygame.event.get():    
            if event.type == pygame.QUIT:  
                run = False
                pygame.quit()

        if not game_over:
            if paddle1.points >= 10:
                winner_text = "Blue Wins!"
                restart_time = current_time + 5000
                game_over = True

            if paddle2.points >= 10:
                winner_text = "Red Wins!"
                restart_time = current_time + 5000
                game_over = True

        if game_over:
            draw_winner(winner_text)
            if current_time > restart_time:
                init()
                game_over = False
            else: 
                continue
            
        # Paddle movement        
        key = pygame.key.get_pressed()  
        if key[pygame.K_w]:
            paddle1.rect.y -= paddle1.paddle_speed  
        if key[pygame.K_s]:
            paddle1.rect.y += paddle1.paddle_speed  
        if key[pygame.K_UP]:
            paddle2.rect.y -= paddle2.paddle_speed
        if key[pygame.K_DOWN]:
            paddle2.rect.y += paddle2.paddle_speed

        # Ensures paddles never move off the screen
        if paddle1.rect.y < 0:
            paddle1.rect.y = 0
        
        if paddle1.rect.y > 425:
            paddle1.rect.y = 425

        if paddle2.rect.y < 0:
            paddle2.rect.y = 0
        
        if paddle2.rect.y > 425:
            paddle2.rect.y = 425

        # Ball movement
        ball.rect.x += ball.speed * ball.dx     
        ball.rect.y += ball.speed * ball.dy     

        # Setting up collision detection with the walls by changing ball's direction
        if ball.rect.y > 490:   
            ball.dy = -1        

        if ball.rect.x > 740:   
            ball.rect.x,ball.rect.y = 375,250     
            paddle1.points += 1

        if ball.rect.y < 10:    
            ball.dy = 1         

        if ball.rect.x < 10:    
            ball.rect.x,250
            paddle2.points += 1

        # Setting up collision detection with the paddles
        if paddle1.rect.colliderect(ball.rect):
            ball.dx = 1     

        if paddle2.rect.colliderect(ball.rect):
            ball.dx = -1

        redraw()    

if __name__ == "__main__":
    main()

显示了我代码的这一部分的消息。

E/Flutter (26162): [ERROR:Flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: This widget has been unmounted,so the State no longer has a context (and should be considered defunct).
E/Flutter (26162): Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.

我没有为此使用任何处置方法。如果有人知道,请告诉我如何解决这个问题。如何处置。我的应用程序关闭后收到崩溃报告,如下所示

@override
  void initState() {
    super.initState();
    try {
      InternetAddress.lookup('google.com').then((result) {
        if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
          // internet conn available

          Navigator.of(context).pushReplacement(MaterialPageRoute(
            builder: (context) =>
                (Constants.prefsMobile.getString("mobile") == null
                    ? Login()
                    // : SignupPayoutPassword(signupdata: [])),: Home(signindata: signinData)),));
        } else {
          // no conn
          _showdialog();
        }
      }).catchError((error) {
        // no conn
        _showdialog();
      });
    } on SocketException catch (_) {
      // no internet
      _showdialog();
    }

    Connectivity()
        .onConnectivityChanged
        .listen((ConnectivityResult connresult) {
      if (connresult == ConnectivityResult.none) {
      } else if (prevIoUs == ConnectivityResult.none) {
        // internet conn
        Navigator.of(context).pop();
        Navigator.of(context).pushReplacement(MaterialPageRoute(
          builder: (context) =>
              (Constants.prefsMobile.getString("mobile") == null
                  ? Login()
                  : Home(signindata: signinData)),));
      }

      prevIoUs = connresult;
    });
  }

这是针对上述问题的崩溃消息吗?请帮忙。

解决方法

请使用。

@override
  void dispose() {
   Connectivity().onConnectivityChanged.cancel();
    super.dispose();
  }

最好在 initState 之外定义您的流:

Stream _connectivityStream = Connectivity().onConnectivityChanged;

并在处置中使用 _connectivityStream.cancel();

该错误意味着您实例化了一个流,该流在事件更改时触发构建更改。此流在 initState 期间设置,这意味着首次创建小部件时。 Connectivity().onConnectivityChanged.listen(....etc)

但是当小部件被释放时,你永远不会告诉 flutter 取消监听这个流。

这就是dispose方法的作用。类似于您希望在构建小部件时如何执行逻辑,您使用 initState,您也应该在您不再对这些逻辑更改感兴趣时告诉它。

如果不这样做,除了内存泄漏之外,还会导致您遇到的错误。

这是您发布的错误 This widget has been unmounted,so the State no longer has a context (and should be considered defunct). 的翻译。 “哎,这个widget已经不在树中了,它的状态没有mounted,我无法重建它,你需要注意它。

请考虑对这些 Flutter 元素使用 dispose 方法,不要提及所有元素,而是从我的脑海中:

  • 动画控制器。
  • 计时器。
  • 流监听器。