flutter开发实战-Webview及dispose关闭背景音

flutter开发实战-Webview及dispose关闭背景音

当在使用webview的时候,dispose需要关闭网页的背景音或者音效。
在这里插入图片描述

一、webview的使用

在工程的pubspec.yaml中引入插件

  webview_flutter: ^4.4.2
  webview_cookie_manager: ^2.0.6
    

Webview的使用代码如下

初始化WebViewController

controller = WebViewController()
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..setBackgroundColor(const Color(0x00000000))
  ..setNavigationDelegate(
    NavigationDelegate(
      onProgress: (int progress) {
        // Update loading bar.
      },
      onPageStarted: (String url) {},
      onPageFinished: (String url) {},
      onHttpError: (HttpResponseError error) {},
      onWebResourceError: (WebResourceError error) {},
      onNavigationRequest: (NavigationRequest request) {
        if (request.url.startsWith('https://www.youtube.com/')) {
          return NavigationDecision.prevent;
        }
        return NavigationDecision.navigate;
      },
    ),
  )
  ..loadRequest(Uri.parse('https://flutter.dev'));
    

将WebViewController传递给WebViewWidget

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: const Text('Flutter Simple Example')),
    body: WebViewWidget(controller: controller),
  );
}
    

二、为了方便使用webview,进行封装成一个独立的widget

为了方便使用webview,进行封装成一个独立的widget

WebAppBar

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

/// 自定义Appbar
class WebAppBar extends StatefulWidget implements PreferredSizeWidget {
  const WebAppBar(
      {Key? key,
      required this.toolbarHeight,
      this.elevation,
      this.backgroundColor,
      this.leadingWidget,
      this.trailingWidget,
      this.centerWidget,
      this.brightness,
      this.backgroundImageName})
      : super(key: key);

  final double toolbarHeight;
  final double? elevation;
  final Color? backgroundColor;
  final Widget? leadingWidget;
  final Widget? trailingWidget;
  final Widget? centerWidget;
  final Brightness? brightness;
  final String? backgroundImageName;

  @override
  // TODO: implement preferredSize
  Size get preferredSize => Size(
      ScreenUtil().screenWidth, toolbarHeight + ScreenUtil().statusBarHeight);

  @override
  State<StatefulWidget> createState() => _WebAppBarState();
}

class _WebAppBarState extends State<WebAppBar> {
  @override
  Widget build(BuildContext context) {
    final SystemUiOverlayStyle overlayStyle =
        widget.brightness == Brightness.dark
            ? SystemUiOverlayStyle.light
            : SystemUiOverlayStyle.dark;

    Widget leadingWidget = (widget.leadingWidget ?? Container());
    Widget centerWidget = (widget.centerWidget ?? Container());
    Widget trailingWidget = (widget.trailingWidget ?? Container());

    return AnnotatedRegion<SystemUiOverlayStyle>(
      //套AnnotatedRegion是为了增加状态栏控制
      value: overlayStyle,
      child: Material(
        color: Colors.transparent,
        //套Material是为了增加elevation
        elevation: widget.elevation ?? 0,
        child: Container(
          padding: EdgeInsets.symmetric(horizontal: 0.0),
          height: widget.toolbarHeight + ScreenUtil().statusBarHeight,
          decoration: BoxDecoration(
            color: widget.backgroundColor,
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Container(
                height: ScreenUtil().statusBarHeight,
              ),
              Expanded(
                child: Container(
                  height: widget.toolbarHeight,
                  alignment: Alignment.center,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Container(
                        height: widget.toolbarHeight,
                        child: leadingWidget,
                      ),
                      Expanded(
                        child: Container(
                          alignment: Alignment.center,
                          height: widget.toolbarHeight,
                          child: centerWidget,
                        ),
                      ),
                      Container(
                        height: widget.toolbarHeight,
                        child: trailingWidget,
                      ),
                    ],
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

    

使用webview的Widget

import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';

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

// #docregion platform_imports
// Import for Android features.
import 'package:webview_flutter_android/webview_flutter_android.dart';

// Import for iOS features.
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
// #enddocregion platform_imports

class WebViewSkeleton extends StatefulWidget {
  const WebViewSkeleton({
    Key? key,
    required this.url,
    required this.onWebProgress,
    required this.onWebResourceError,
    required this.onLoadFinished,
    this.onWebTitleLoaded,
    required this.onWebViewCreated,
    this.appUserAgent,
    this.webViewUserAgent,
  }) : super(key: key);

  final String url;
  final String? appUserAgent;
  final String? webViewUserAgent;
  final Function(int progress) onWebProgress;
  final Function(WebResourceError error) onWebResourceError;
  final Function(String? url) onLoadFinished;
  final Function(String? webTitle)? onWebTitleLoaded;
  final Function(WebViewController controller) onWebViewCreated;

  @override
  State<WebViewSkeleton> createState() => _WebViewSkeletonState();
}

class _WebViewSkeletonState extends State<WebViewSkeleton> {
  // WebViewController
  late final WebViewController _webController;

  // 尝试3次,每次间隔2秒
  int _loadTitleTimes = 0;

  bool _isDisposed = false;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _isDisposed = false;
    initWebController();
  }

  void initWebController() {
    // #docregion platform_features
    late final PlatformWebViewControllerCreationParams params;
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
      );
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }

    final WebViewController controller =
        WebViewController.fromPlatformCreationParams(params);
    // #enddocregion platform_features

    controller
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..setUserAgent(widget.webViewUserAgent)
      ..setNavigationDelegate(
        NavigationDelegate(
          onProgress: (int progress) {
            debugPrint('WebView is loading (progress : $progress%)');
            widget.onWebProgress(progress);
          },
          onPageStarted: (String url) {
            debugPrint('Page started loading: $url');
            // 网页开始加载
            webPageLoadedStart();
            print('onPageStarted url: $url');
          },
          onPageFinished: (String url) {
            debugPrint('Page finished loading: $url');
            // 网页加载完成
            print('onPageFinished url: $url');

            // 加载完成
            widget.onLoadFinished(url);

            // 获取网页的标题
            getWebPageTitle(url: url);
          },
          onWebResourceError: (WebResourceError error) {
            debugPrint('''
Page resource error:
  code: ${error.errorCode}
  description: ${error.description}
  errorType: ${error.errorType}
  isForMainFrame: ${error.isForMainFrame}
          ''');
            print("onWebResourceError:${error}");
            widget.onWebResourceError(error);
          },
          onNavigationRequest: (NavigationRequest request) {
            String url = Uri.decodeComponent(request.url);
            bool canNavigate = false;
            if (url.startsWith("http")) {
              canNavigate = true;
            }
            // 允许路由替换
            return canNavigate
                ? NavigationDecision.navigate
                : NavigationDecision.prevent;
          },
          onUrlChange: (UrlChange change) {
            debugPrint('url change to ${change.url}');
          },
          // onHttpAuthRequest: (HttpAuthRequest request) {
          //   openDialog(request);
          // },
        ),
      );

    // #docregion platform_features
    if (controller.platform is AndroidWebViewController) {
      AndroidWebViewController.enableDebugging(true);
      (controller.platform as AndroidWebViewController)
          .setMediaPlaybackRequiresUserGesture(false);
    }
    // #enddocregion platform_features

    _webController = controller;
    onWebViewCreated();
  }

  void onWebViewCreated() {
    print("onWebViewCreated");
    // controller.loadUrl(url);此时也可以初始化一个url
    _webController.canGoBack().then((res) {
      // 是否能返回上一级
      print("controller.canGoBack res: $res");
    });
    _webController.currentUrl().then((url) {
      // 返回当前url
      print("controller.currentUrl url: $url");
    });
    _webController.canGoForward().then((res) {
      //是否能前进
      print("controller.canGoForward res: $res");
    });

    String filePre = "file://";
    if (widget.url.startsWith(filePre)) {
      String html = widget.url.substring(filePre.length);
      DefaultAssetBundle.of(context)
          .loadString('assets/htmls/${html}')
          .then((value) => _webController?.loadHtmlString(value));
    } else {
      if (widget.url.startsWith("http://") ||
          widget.url.startsWith("https://")) {
        _webController.loadRequest(Uri.parse(widget.url), headers: {
          'Referer': widget.url,
        });
      }
    }

    widget.onWebViewCreated(_webController);
  }

  @override
  void dispose() {
    // TODO: implement dispose
    print("_WebViewSkeletonState dispose");
    _isDisposed = true;
    webControllerDispose();
    super.dispose();
  }

  Future<void> webControllerDispose() async {
    /// dispose打开空白页面,关闭音频
    String url = "about:blank";
    await _webController?.loadRequest(Uri.parse(url), headers: {

    });
    _webController?.clearCache();
    _webController?.clearLocalStorage();
  }

  void webPageLoadedStart() {
    _loadTitleTimes = 0;
  }

  Future<void> getWebPageTitle({required String url}) async {
    if (_isDisposed) {
      return;
    }

    String? title = await _webController?.getTitle();
    print("getWebPageTitle:${title}");
    if (title != null && title.isNotEmpty) {
      print("webTitle a:${title}");
      setWebPageTitle(title);
    } else {
      try {
        var result = await _webController
            ?.runJavaScriptReturningResult('window.document.title');
        print("webTitle document.url:${result}");
        if (result != null && (result is String) && result.isNotEmpty) {
          setWebPageTitle(result);
        } else {
          result = await _webController?.runJavaScriptReturningResult(
              'window.document.getElementsByTagName("title")[0]');
          print("webTitle document.getElementsByTagName:${result}");
          setWebPageTitle(result);
        }
      } catch (e) {
        print("getWebPageTitle:${e.toString()}");
        // 最多尝试三次
        if (_loadTitleTimes < 3) {
          Future.delayed(Duration(seconds: 2), () {
            _loadTitleTimes++;
            getWebPageTitle(url: url);
          });
        }
      }
    }
  }

  // 设置页面标题
  void setWebPageTitle(data) {
    if (widget.onWebTitleLoaded != null) {
      widget.onWebTitleLoaded!(data);
    }
  }

  // 返回
  void goBack() {
    _webController?.canGoBack().then((res) {
      // 是否能返回上一级
      print("controller.canGoBack res: $res");
      if (true == res) {
        _webController?.goBack();
      }
    });
  }

  // 刷新
  void reload() {
    _webController?.reload();
  }

  @override
  Widget build(BuildContext context) {
    return buildWebView(context);
  }

  Widget buildWebView(BuildContext context) {
    return WebViewWidget(
      controller: _webController,
    );
  }
}

    

使用web view的页面webviewPage

class WebViewPage extends StatefulWidget {
  const WebViewPage({
    Key? key,
    this.arguments,
  }) : super(key: key);

  final Object? arguments;

  @override
  State<WebViewPage> createState() => _WebViewPageState();
}

class _WebViewPageState extends State<WebViewPage> {
  String title = "";
  String? url;

  // WebViewController
  WebViewController? _webViewController;

  double webProgress = 0.0;

  String? webViewUserAgent;
  String? appUserAgent;
  String? webTitle;

  @override
  void initState() {
    // TODO: implement initState
    if (widget.arguments != null && widget.arguments is Map) {
      Map obj = widget.arguments as Map;
      url = obj["url"];
      webViewUserAgent = obj['webViewUserAgent'];
      appUserAgent = obj['appUserAgent'];
      webTitle = obj['webTitle'];
    }

    loggerInfo("_WebViewPageState arguments:${widget.arguments}");

    loggerInfo("_WebViewPageState url:${url}");

    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: WebAppBar(
          toolbarHeight: 44.0,
          backgroundColor: Theme.of(context).primaryColor,
          centerWidget: Text(
            webTitle ?? title,
            textAlign: TextAlign.center,
            overflow: TextOverflow.ellipsis,
            style: TextStyle(
              fontSize: 17,
              color: ColorUtil.hexColor(0xffffff),
              fontWeight: FontWeight.w600,
              fontStyle: FontStyle.normal,
              decoration: TextDecoration.none,
            ),
          ),
          leadingWidget: Row(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              IconButton(
                padding: EdgeInsets.all(0.0),
                onPressed: () {
                  webViewGoBack(context);
                },
                icon: Icon(
                  Icons.arrow_back_ios,
                  color: Colors.white,
                  size: 24.0,
                ),
              ),
              IconButton(
                padding: EdgeInsets.all(0.0),
                onPressed: () {
                  navigatorBack(context);
                },
                icon: Icon(
                  Icons.close_rounded,
                  color: Colors.white,
                  size: 30.0,
                ),
              ),
            ],
          ),
          trailingWidget: Row(
            mainAxisAlignment: MainAxisAlignment.end,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              SizedBox(
                width: 28.0,
              ),
              IconButton(
                padding: EdgeInsets.all(0.0),
                onPressed: () {
                  webViewReload();
                },
                icon: Icon(
                  Icons.refresh_outlined,
                  color: Colors.white,
                  size: 28.0,
                ),
              ),
            ],
          ),
        ),
        body: Stack(
          children: [
            WebViewSkeleton(
              url: url ?? "",
              onWebResourceError: (WebResourceError error) {
                if (mounted) {
                  // TODO onWebResourceError
                }
              },
              onWebProgress: (int progress) {
                if (mounted) {
                  // TODO onWebProgress
                  double precent = progress / 100.0;
                  if (precent > 1.0) {
                    precent = 1.0;
                  }

                  if (precent < 0.0) {
                    precent = 0.0;
                  }

                  setState(() {
                    webProgress = precent;
                    loggerInfo("webProgress:${webProgress}");
                  });
                }
              },
              onLoadFinished: (String? url) {
                if (mounted) {
                  // TODO onLoadFinished
                }
              },
              onWebTitleLoaded: (String? webTitle) {
                if (mounted) {
                  String? aWebTitle;
                  if ('""' != webTitle) {
                    aWebTitle = webTitle;
                  }
                  setState(() {
                    title = aWebTitle ?? "";
                  });
                }
              },
              onWebViewCreated: (WebViewController controller) {
                _webViewController = controller;
              },
            ),
            buildProgressIndicator(context),
          ],
        ),
    );
  }

  Widget buildProgressIndicator(BuildContext context) {
    return (webProgress != 1.0)
        ? LinearProgressIndicator(
            backgroundColor: Colors.transparent,
            valueColor: AlwaysStoppedAnimation(ColorUtil.hexColor(0x3b93ff)),
            value: webProgress,
            minHeight: 2,
          )
        : Container();
  }

  void navigatorBack(BuildContext context) {
    Navigator.of(context).pop();
  }

  void webViewGoBack(BuildContext context) {
    _webViewController?.canGoBack().then((res) {
      // 是否能返回上一级
      loggerInfo("controller.canGoBack res: $res");
      if (true == res) {
        _webViewController?.goBack();
      } else {
        navigatorBack(context);
      }
    });
  }

  void webViewReload() {
    _webViewController?.reload();
  }
}
    

三、解决dispose关闭背景音乐

解决dispose关闭背景音乐的问题,当widget被dispose的时候,我们可以通过加载一个空白页面,来实现这个关闭背景音乐。
加载空白

代码如下

@override
  void dispose() {
    // TODO: implement dispose
    print("_WebViewSkeletonState dispose");
    _isDisposed = true;
    webControllerDispose();
    super.dispose();
  }

  Future<void> webControllerDispose() async {
    /// dispose打开空白页面,关闭音频
    String url = "about:blank";
    await _webController?.loadRequest(Uri.parse(url), headers: {

    });
    _webController?.clearCache();
    _webController?.clearLocalStorage();
  }
    

四、小结

flutter开发实战-Webview及dispose关闭背景音

学习记录,每天不停进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/778012.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AJAX-个人版-思路步骤整理版

前置知识&#xff1a;老式的web创建工程方法就是创建项目然后添加web工件&#xff0c;然后添加lib依赖如&#xff1a;tomcat,servlet&#xff0c;等。 传统请求 对于传统请求操作&#xff1a;整体流程也就是创建静态页面&#xff0c; <!DOCTYPE html> <html lang&q…

每日一题~ leetcode 402 (贪心+单调栈)

click me! 这个贪心的推导在leetcode上已经很明确了。 click me! 删除k个数&#xff0c;可以先考虑删除一个数。这也是一种常见的思路。&#xff08;如果进行同样的操作多次&#xff0c;可以先只 考虑一次操作如何实现&#xff0c;或者他的影响。完成这一次操作后&#xff0c;…

MySQL基础篇(二)

如何创建一个数据库&#xff1a; create database 数据库名; 使用数据库&#xff1a; use 数据库名&#xff1b; 如何查看都有哪些数据库&#xff1a; use databases;//后面需要加s 容易忘 如何查看都有哪些表&#xff1a; use tables;//后面需要加s 如何清屏&#xff…

texStudio使用(小白)

原先使用overleaf在线编译&#xff0c;可能eps格式的图片太大导致需要充钱&#xff0c;所以考虑本地安装 安装教程参考B站视频&#xff1a;B站Latex本地编译器安装&#xff1a;TexLive TextStudio 踩到坑&#xff1a; 1. 编译器位置要选择对 因为BibTex选成了Biber导致出现无…

【反悔堆 优先队列 临项交换 决策包容性】630. 课程表 III

本文涉及知识点 贪心 反悔堆 优先队列 临项交换 Leetcode630. 课程表 III 这里有 n 门不同的在线课程&#xff0c;按从 1 到 n 编号。给你一个数组 courses &#xff0c;其中 courses[i] [durationi, lastDayi] 表示第 i 门课将会 持续 上 durationi 天课&#xff0c;并且必…

为什么建议 MySQL 数据库字段一定要设置 NOT NULL

1. 前言 建议 MySQL 数据库字段一定要设置 NOT NULL 这句建议你可能听好多人讲过&#xff0c;但是有没有仔细想过为什么别人这么说 &#xff1f; 在实际开发中&#xff0c;对使不使用 not null 很多人并没有一个明确的标准&#xff0c;要知道某个字段需不需要添加 not null&a…

深度学习:为什么说英伟达A100或RTX A6000等专业GPU比RTX 4090更适合深度学习呢?

目录 一、关键术语 CUDA cores&#xff08;CUDA内核&#xff09;&#xff1a; memory bandwidth&#xff08;内存带宽&#xff09;&#xff1a; 二、深度学习的显卡硬件要求 三、NVIDIA显卡A100、RTX A6000和RTX 4090对比 1、NVIDIA A100 2、NVIDIA RTX A6000 3、NVIDI…

BufferReader/BufferWriter使用时出现的问题

项目场景&#xff1a; 在一个文件中有一些数据&#xff0c;需要读取出来并替换成其他字符再写回文件中&#xff0c;需要用Buffer流。 问题描述 文件中的数据丢失&#xff0c;并且在读取前就为空&#xff0c;读取不到数据。 问题代码&#xff1a; File f new File("D:\\…

【算法专题】双指针算法

1. 移动零 题目分析 对于这类数组分块的问题&#xff0c;我们应该首先想到用双指针的思路来进行处理&#xff0c;因为数组可以通过下标进行访问&#xff0c;所以说我们不用真的定义指针&#xff0c;用下标即可。比如本题就要求将数组划分为零区域和非零区域&#xff0c;我们不…

51单片机基础10——串口实验

串口实验 51单片机串口实验1. 软硬件条件2. 串口实验2.1 单片机与PC 发送字符2.1.1 效果2.1.2 代码2.1.3 优化 2.3 串口接收数据(指令控制单片机)2.3.1 非中断方式实现2.3.2 中断方式实现 51单片机串口实验 1. 软硬件条件 单片机型号&#xff1a;STC89C52RC开发环境&#xff…

suricata7 rule加载(一)加载 action

suricata7.0.5 一、前提条件 1.1 关键字注册 main | --> SuricataMain|--> PostConfLoadedSetup|--> SigTableSetupsigmatch_table是一个全局数组&#xff0c;每个元素就是一个关键字节点&#xff0c;是对关键字如何处理等相关回调函数。非常重要的一个结构&#x…

DevOps实战:使用GitLab+Jenkins+Kubernetes(k8s)建立CI_CD解决方案

一.系统环境 本文主要基于Kubernetes1.21.9和Linux操作系统CentOS7.4。 服务器版本docker软件版本Kubernetes(k8s)集群版本CPU架构CentOS Linux release 7.4.1708 (Core)Docker version 20.10.12v1.21.9x86_64CI/CD解决方案架构图:CI/CD解决方案架构图描述:程序员写好代码之…

Python通过HiperMATRIX API写数据

PyCharm编程和调试 其中token 我偷懒了&#xff0c;只是调试&#xff0c;打开HiperMATRIX界面&#xff0c;登录&#xff0c;从浏览器console里面找到token value。 代码片段 import random, time, requests, jsonhipermatrix_api_url http://192.168.1.240:9030/api/edge-ma…

GlusterFS分布式存储系统

GlusterFS分布式存储系统 一&#xff0c;分布式文件系统理论基础 1.1 分布式文件系统出现 计算机通过文件系统管理&#xff0c;存储数据&#xff0c;而现在数据信息爆炸的时代中人们可以获取的数据成指数倍的增长&#xff0c;单纯通过增加硬盘个数来扩展计算机文件系统的存储…

Stable Diffusion:最全详细图解

Stable Diffusion&#xff0c;作为一种革命性的图像生成模型&#xff0c;自发布以来便因其卓越的生成质量和高效的计算性能而受到广泛关注。不同于以往的生成模型&#xff0c;Stable Diffusion在生成图像的过程中&#xff0c;采用了独特的扩散过程&#xff0c;结合深度学习技术…

SelectIO(参考ug471)

目录 SelectIO常用原语IBUF/IBUFGIBUFDS/IBUFGDSIOBUFIOBUFDSOBUFOBUFDSOBUFTOBUFTDS 常用 IO 约束PACKAGE_PINIOSTANDARDIBUF_LOW_PWRSLEWDRIVEPULLTYPEDIFF_TERMDIFF_TERM_ADVIOB SelectIO 逻辑资源HR和HP I/O Banks 区别ILOGIC结构图IDDR原语OPPOSITE_EDGE ModeSAME_EDGE Mo…

Elasticsearch 实现 Word、PDF,TXT 文件的全文内容提取与检索

文章目录 一、安装软件:1.通过docker安装好Es、kibana安装kibana:2.安装原文检索与分词插件:之后我们可以通过doc命令查看下载的镜像以及运行的状态:二、创建管道pipeline名称为attachment二、创建索引映射:用于存放上传文件的信息三、SpringBoot整合对于原文检索1、导入依赖…

Lua语言入门

目录 Lua语言1 搭建Lua开发环境1.1 安装Lua解释器WindowsLinux 1.2 IntelliJ安装Lua插件在线安装本地安装 2 Lua语法2.1 数据类型2.2 变量全局变量局部变量命名规范局部变量作用域 2.3 注释单行注释多行注释 2.4 赋值2.5 操作符数学操作符比较操作符逻辑操作符连接操作符取长度…

计算机网络(2

计算机网络续 一. 网络编程 网络编程, 指网络上的主机, 通过不同的进程, 以编程的方式实现网络通信(或网络数据传输). 即便是同一个主机, 只要不同进程, 基于网络来传输数据, 也属于网络编程. 二. 网络编程套接字(socket) socket: 操作系统提供的网络编程的 API 称作 “soc…

7 系列 FPGA 引脚及封装(参考ug475)

目录 I/O BankPins引脚定义I/O and Multi-Function PinsPower Supply PinsDedicated XADC PinsTransceiver PinsDedicated Configuration PinsTemperature Sensor Pins Device 视图整个 FPGAIOBILOGIC,OLOGIC,IDELAY,ODELAYBUFIO,BUFR,IDELAYCTRLBUFMRCEBRAM,DSPIBUFDS_GTE2CLB…