<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      網(wǎng)頁(yè)數(shù)據(jù)訪問

      接口準(zhǔn)備json數(shù)據(jù)

      static const String kBaseUrl = 'https://www.wanandroid.com';
      完整的json數(shù)據(jù)連接長(zhǎng)這樣-> https://www.wanandroid.com/article/list/0/json 這里只使用一個(gè)獲取文章列表的如下接口,其中 0 是個(gè)可以改變的參數(shù),表示文章的頁(yè)數(shù)。

      img

      如圖所示,主要的信息都在datas里面,所以,我們只需要解析datas里面的數(shù)據(jù)即可。

      class ArticleApi {
        static const String kBaseUrl = 'https://www.wanandroid.com';
      
        final Dio _client = Dio(BaseOptions(
          baseUrl: kBaseUrl,
        ));
        Future<List<Article>> loadArticles(int page) async {
          String path = '/article/list/$page/json';  
          var rep = await _client.get(path);  //拼接地址
          if (rep.statusCode == 200) {
            if (rep.data != null) {
              var data = rep.data['data']['datas'] as List; //當(dāng)前page獲取所有data里面datas的數(shù)據(jù)
              return data.map(Article.formMap).toList();
            }
          }
          return [];
        }
      }
      

      var data內(nèi)容如下:

      img

      Dio

      網(wǎng)絡(luò)請(qǐng)求是非常通用的能力,開發(fā)者自己來寫非常復(fù)雜,所以一般使用三方的依賴庫(kù)。對(duì)于 Flutter 網(wǎng)絡(luò)請(qǐng)求來說,最受歡迎的是 dio , 使用前先添加依賴

      在 ArticleApi 中持有 Dio 類型的 _client 對(duì)象,構(gòu)造時(shí)可以設(shè)置 baseUrl 。然后提供 loadArticles 方法,用于加載第 page 頁(yè)的數(shù)據(jù),其中的邏輯處理,就是加載網(wǎng)絡(luò)數(shù)據(jù)的核心。

      使用起來也很方便,提供 Dio#get 方法就可以異步獲取數(shù)據(jù),得到之后,從結(jié)果中拿到自己想要的數(shù)據(jù),生成 Article 列表即可。

      介紹 Dio

      Dio 是一個(gè)強(qiáng)大的 Flutter 和 Dart HTTP 客戶端庫(kù),用于處理網(wǎng)絡(luò)請(qǐng)求。它提供了簡(jiǎn)單易用的 API,支持多種功能,如攔截器、請(qǐng)求取消、超時(shí)設(shè)置、文件上傳下載等。以下是 Dio 的一些主要特點(diǎn)和使用方法:

      主要特點(diǎn)

      1. 支持多種請(qǐng)求方法:GET、POST、PUT、DELETE、HEAD、PATCH 等。
      2. 攔截器:可以在請(qǐng)求發(fā)送前和響應(yīng)接收后進(jìn)行攔截處理。
      3. 請(qǐng)求取消:可以取消正在進(jìn)行的請(qǐng)求。
      4. 超時(shí)設(shè)置:可以設(shè)置連接超時(shí)和接收超時(shí)。
      5. 文件上傳下載:支持文件的上傳和下載。
      6. 轉(zhuǎn)換器:支持多種數(shù)據(jù)格式的轉(zhuǎn)換,如 JSON、FormData 等。
      7. Cookie 管理:內(nèi)置 Cookie 管理器。

      使用方法

      1. 添加依賴

        pubspec.yaml 文件中添加 Dio 依賴:

        dependencies:
          dio: ^5.0.0
        
      2. 導(dǎo)入庫(kù)

        在 Dart 文件中導(dǎo)入 Dio 庫(kù):

        import 'package:dio/dio.dart';
        
      3. 創(chuàng)建 Dio 實(shí)例

        創(chuàng)建一個(gè) Dio 實(shí)例,并可以設(shè)置基礎(chǔ) URL 和其他選項(xiàng):

        final Dio dio = Dio(BaseOptions(
          baseUrl: 'https://www.wanandroid.com',
          connectTimeout: 5000, // 連接超時(shí)時(shí)間
          receiveTimeout: 3000, // 接收超時(shí)時(shí)間
        ));
        
      4. 發(fā)送請(qǐng)求

        使用 Dio 實(shí)例發(fā)送請(qǐng)求,例如 GET 請(qǐng)求:

        try {
          Response response = await dio.get('/article/list/0/json');
          if (response.statusCode == 200) {
            print(response.data);
          }
        } catch (e) {
          print(e);
        }
        
      5. 處理響應(yīng)

        處理響應(yīng)數(shù)據(jù),例如解析 JSON 數(shù)據(jù):

        try {
          Response response = await dio.get('/article/list/0/json');
          if (response.statusCode == 200) {
            var data = response.data['data']['datas'] as List;
            List<Article> articles = data.map(Article.formMap).toList();
            print(articles);
          }
        } catch (e) {
          print(e);
        }
        
      6. 使用攔截器

        添加請(qǐng)求和響應(yīng)攔截器:

        dio.interceptors.add(InterceptorsWrapper(
          onRequest: (options, handler) {
            print('Sending request: ${options.method} ${options.uri}');
            return handler.next(options);
          },
          onResponse: (response, handler) {
            print('Received response: ${response.statusCode}');
            return handler.next(response);
          },
          onError: (DioError e, handler) {
            print('Request error: ${e.message}');
            return handler.next(e);
          },
        ));
        

      ArticleformMap

      class Article {
        final String title;
        final String url;
        final String time;
      
        const Article({
          required this.title,
          required this.url,
          required this.time,
        });
      
        factory Article.formMap(dynamic map){
          return Article(
            title: map['title'] ?? '未知',
            url: map['link'] ?? '',
            time: map['niceDate'] ?? '',
          );
        }
      
        @override
        String toString() {
          return 'Article{title: $title, url: $url, time: $time}';
        }
        
      }
      

      解釋 factory Article.formMap(dynamic map)

      在 Dart 中,factory 構(gòu)造函數(shù)用于創(chuàng)建類的實(shí)例,但它提供了一種靈活性,允許在構(gòu)造函數(shù)中返回一個(gè)已經(jīng)存在的實(shí)例,而不是總是創(chuàng)建一個(gè)新的實(shí)例。這在需要實(shí)現(xiàn)單例模式或從緩存中返回對(duì)象時(shí)非常有用。

      具體到 factory Article.formMap(dynamic map),這個(gè)構(gòu)造函數(shù)的作用是從一個(gè) Map 對(duì)象中解析數(shù)據(jù),并創(chuàng)建一個(gè) Article 對(duì)象。以下是詳細(xì)的解釋:

      1. 工廠構(gòu)造函數(shù)

        • factory 關(guān)鍵字表示這是一個(gè)工廠構(gòu)造函數(shù)。
        • 工廠構(gòu)造函數(shù)可以返回一個(gè)緩存的實(shí)例,或者根據(jù)條件返回不同的實(shí)例。
      2. 參數(shù)

        • dynamic map:表示傳入的數(shù)據(jù)是一個(gè)動(dòng)態(tài)類型的 Map 對(duì)象,通常是從 JSON 解析得到的數(shù)據(jù)。
      3. 作用

        • 從傳入的 Map 對(duì)象中提取數(shù)據(jù)。
        • 使用提取的數(shù)據(jù)創(chuàng)建并返回一個(gè) Article 對(duì)象。

      示例代碼

      假設(shè) Article 類的定義如下:

      class Article {
        final int id;
        final String title;
        final String author;
      
        Article({required this.id, required this.title, required this.author});
      
        // 工廠構(gòu)造函數(shù),從 Map 對(duì)象創(chuàng)建 Article 實(shí)例
        factory Article.formMap(dynamic map) {
          return Article(
            id: map['id'] as int,
            title: map['title'] as String,
            author: map['author'] as String,
          );
        }
      
        @override
        String toString() {
          return 'Article{id: $id, title: $title, author: $author}';
        }
      }
      

      解釋示例代碼

      1. 類定義

        • Article 類包含三個(gè)屬性:idtitleauthor
      2. 構(gòu)造函數(shù)

        • Article({required this.id, required this.title, required this.author}):標(biāo)準(zhǔn)的構(gòu)造函數(shù),用于創(chuàng)建 Article 對(duì)象。
      3. 工廠構(gòu)造函數(shù)

        • factory Article.formMap(dynamic map):工廠構(gòu)造函數(shù),從 Map 對(duì)象中提取數(shù)據(jù)并創(chuàng)建 Article 對(duì)象。
        • map['id'] as int:從 Map 中提取 id 并轉(zhuǎn)換為 int 類型。
        • map['title'] as String:從 Map 中提取 title 并轉(zhuǎn)換為 String 類型。
        • map['author'] as String:從 Map 中提取 author 并轉(zhuǎn)換為 String 類型。
        • 返回一個(gè)新的 Article 對(duì)象。

      使用示例

      假設(shè)從網(wǎng)絡(luò)請(qǐng)求中獲取到的 JSON 數(shù)據(jù)如下:

      {
        "id": 1,
        "title": "Flutter 網(wǎng)絡(luò)請(qǐng)求",
        "author": "張三"
      }
      

      解析并創(chuàng)建 Article 對(duì)象的代碼如下:

      void main() {
        Map<String, dynamic> jsonData = {
          "id": 1,
          "title": "Flutter 網(wǎng)絡(luò)請(qǐng)求",
          "author": "張三"
        };
      
        Article article = Article.formMap(jsonData);
        print(article); // 輸出: Article{id: 1, title: Flutter 網(wǎng)絡(luò)請(qǐng)求, author: 張三}
      }
      

      通過這種方式,factory Article.formMap(dynamic map) 提供了一種方便且類型安全的方法,從 JSON 數(shù)據(jù)中創(chuàng)建 Article 對(duì)象。

      為什么需要重寫 toString 方法

      Dart 中,每個(gè)類都繼承自 Object 類,而 Object 類提供了一個(gè)默認(rèn)的 toString 方法。默認(rèn)的 toString 方法返回的是類的名稱和對(duì)象的內(nèi)存地址,例如 Instance of 'Article'。這種默認(rèn)的字符串表示通常不夠詳細(xì),無法提供對(duì)象的具體內(nèi)容。

      重寫 toString 方法可以提供一個(gè)更具可讀性的字符串表示,便于調(diào)試和日志記錄。具體來說,重寫 toString 方法有以下幾個(gè)好處:

      • 調(diào)試方便:
        在調(diào)試過程中,可以直接查看對(duì)象的具體屬性值,而不是只能看到內(nèi)存地址。
        便于打印對(duì)象信息,快速定位問題。
      • 日志記錄:
        在日志中記錄對(duì)象信息時(shí),可以提供更詳細(xì)的上下文。
        便于后續(xù)分析和問題排查。
      • 代碼可讀性:
        提高代碼的可讀性和可維護(hù)性。
        其他開發(fā)者可以更容易地理解對(duì)象的內(nèi)容。

      AriticleCotent

      img

       @override
        Widget build(BuildContext context) {
          if (_loading) {  //如果 _loading 為 true,則執(zhí)行代碼塊中的內(nèi)容。
            return Center( //Center 小部件用于將子小部件居中顯示。
              child: Wrap(
                spacing: 10, //設(shè)置子小部件之間的間距為 10 像素。
                direction: Axis.vertical, //設(shè)置排列方向?yàn)榇怪狈较颉?          crossAxisAlignment:WrapCrossAlignment.center, //設(shè)置子小部件在交叉軸(水平軸)上的對(duì)齊方式為居中對(duì)齊。
                children: const [
                  CupertinoActivityIndicator(), //顯示一個(gè) iOS 風(fēng)格的加載指示器。
                  Text(
                    "數(shù)據(jù)加載中,請(qǐng)稍后...",
                    style: TextStyle(color: Colors.grey),  //顯示一條加載提示文本,文本顏色為灰色。
                  )
                ],
              ),
            );
          }
      
      
      import 'dart:async';
      
      import 'package:flutter/cupertino.dart';
      import 'package:flutter/material.dart';
      import 'package:net_article/api/article_api.dart';
      import 'package:net_article/model/article.dart';
      import 'package:flutter/cupertino.dart';
      import 'package:easy_refresh/easy_refresh.dart';
      
      import 'article_detail_page.dart';
      
      class AriticleCotent extends StatefulWidget {
        const AriticleCotent({Key? key}) : super(key: key);
      
        @override
        State<AriticleCotent> createState() => _AriticleCotentState();
      }
      
      class _AriticleCotentState extends State<AriticleCotent> {
        List<Article> _articles = [];
      
        ArticleApi api = ArticleApi();
      
        bool _loading = false;
        @override
        void initState() {
          super.initState();
          _loadData();
        }
      
        void _loadData() async {
          _loading = true;
          setState(() {});
          _articles = await api.loadArticles(0);
          _loading = false;
          setState(() {});
        }
      
        @override
        Widget build(BuildContext context) {
          if (_loading) {  //如果 _loading 為 true,則執(zhí)行代碼塊中的內(nèi)容。
            return Center( //Center 小部件用于將子小部件居中顯示。
              child: Wrap(
                spacing: 10, //設(shè)置子小部件之間的間距為 10 像素。
                direction: Axis.vertical, //設(shè)置排列方向?yàn)榇怪狈较颉?          crossAxisAlignment:WrapCrossAlignment.center, //設(shè)置子小部件在交叉軸(水平軸)上的對(duì)齊方式為居中對(duì)齊。
                children: const [
                  CupertinoActivityIndicator(), //顯示一個(gè) iOS 風(fēng)格的加載指示器。
                  Text(
                    "數(shù)據(jù)加載中,請(qǐng)稍后...",
                    style: TextStyle(color: Colors.grey),  //顯示一條加載提示文本,文本顏色為灰色。
                  )
                ],
              ),
            );
          }
      
          return EasyRefresh( //小部件:用于實(shí)現(xiàn)下拉刷新和上拉加載更多的功能。
            header: const ClassicHeader( //ClassicHeader 是 EasyRefresh 提供的一個(gè)經(jīng)典風(fēng)格的下拉刷新頭部。
              dragText: "下拉加載",
              armedText: "釋放刷新",
              readyText: "開始加載",
              processingText: "正在加載",
              processedText: "刷新成功",
            ),
            footer: const ClassicFooter(processingText: "正在加載"),
            // dragText: "下拉加載":當(dāng)用戶下拉時(shí)顯示的文本。
            // armedText: "釋放刷新":當(dāng)用戶下拉到一定距離時(shí)顯示的文本。
            // readyText: "開始加載":當(dāng)用戶釋放手指準(zhǔn)備刷新時(shí)顯示的文本。
            // processingText: "正在加載":刷新過程中顯示的文本。
            // processedText: "刷新成功":刷新完成后顯示的文本。
            // ClassicFooter 是 EasyRefresh 提供的一個(gè)經(jīng)典風(fēng)格的上拉加載更多底部。
            // processingText: "正在加載":加載過程中顯示的文本。
      
            onRefresh: _onRefresh,
            onLoad: _onLoad, //指定加載更多時(shí)調(diào)用的方法。
            child: ListView.builder( //用于創(chuàng)建一個(gè)可滾動(dòng)的列表視圖。
              itemExtent: 80,
              itemCount: _articles.length,
              itemBuilder: _buildItemByIndex,
              // itemExtent: 80:設(shè)置每個(gè)列表項(xiàng)的高度為 80 像素。
              // itemCount: _articles.length:設(shè)置列表項(xiàng)的數(shù)量為 _articles 列表的長(zhǎng)度。
              // itemBuilder: _buildItemByIndex:指定構(gòu)建每個(gè)列表項(xiàng)的方法。
            ),
          );
        }
      
        void _onRefresh() async {
          _articles = await api.loadArticles(0);
          setState(() {});
        }
      
        void _onLoad() async {
          int nextPage = _articles.length ~/ 20;
          List<Article> newArticles = await api.loadArticles(nextPage);
          _articles = _articles + newArticles;
          setState(() {});
        }
      
        Widget _buildItemByIndex(BuildContext context, int index) {
          print('點(diǎn)擊了第 $index 個(gè) item}');
          return ArticleItem(
            article: _articles[index], //index,從0開始自動(dòng)增長(zhǎng)
            onTap: _jumpToPage, //把當(dāng)前article傳給_jumpToPage
          );
        }
      
        void _jumpToPage(Article article) {
          Navigator.of(context).push(
            MaterialPageRoute(
              builder: (_) => ArticleDetailPage(article: article), //跳轉(zhuǎn)到詳情界面
            ),
          );
        }
      }
      
      class ArticleItem extends StatelessWidget {
        final Article article;
        final ValueChanged<Article> onTap;
      
        const ArticleItem({Key? key, required this.article, required this.onTap})
            : super(key: key);
      
        @override
        Widget build(BuildContext context) {
          return GestureDetector(
            onTap: () => onTap(article),
            child: Card(
              elevation: 0,
              shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
              color: Colors.white,
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      children: [
                        Expanded(
                          child: Text(
                            article.title,
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                            style:
                                TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
                          ),
                        ),
                        const SizedBox(
                          width: 10,
                        ),
                        // Spacer(),
                        Text(
                          article.time,
                          style: TextStyle(fontSize: 12, color: Colors.grey),
                        ),
                      ],
                    ),
                    const SizedBox(
                      height: 4,
                    ),
                    Expanded(
                      child: Align(
                        alignment: Alignment.centerLeft,
                        child: Text(
                          article.url,
                          style: TextStyle(fontSize: 12, color: Colors.grey),
                          maxLines: 2,
                          overflow: TextOverflow.ellipsis,
                        ),
                      ),
                    )
                  ],
                ),
              ),
            ),
          );
        }
      }
      

      webview_flutter

      代碼解釋

      這段代碼定義了一個(gè) Flutter 應(yīng)用中的 ArticleDetailPage 頁(yè)面,用于顯示文章詳情。頁(yè)面中使用了 WebViewWidget 來加載并顯示文章的網(wǎng)頁(yè)內(nèi)容。以下是代碼的具體解釋:

      1. 導(dǎo)入包

      import 'package:flutter/material.dart';
      import '../model/article.dart';
      import 'package:webview_flutter/webview_flutter.dart';
      
      • flutter/material.dart:導(dǎo)入 Flutter 的 Material Design 組件庫(kù)。
      • ../model/article.dart:導(dǎo)入自定義的 Article 模型類,用于表示文章數(shù)據(jù)。
      • webview_flutter/webview_flutter.dart:導(dǎo)入 webview_flutter 包,用于在 Flutter 中嵌入 WebView。

      2. 定義 ArticleDetailPage

      class ArticleDetailPage extends StatefulWidget {
        final Article article;
        const ArticleDetailPage({Key? key, required this.article}) : super(key: key);
      
        @override
        State<ArticleDetailPage> createState() => _ArticleDetailPageState();
      }
      
      • ArticleDetailPage 是一個(gè)有狀態(tài)的 Widget (StatefulWidget),它接收一個(gè) Article 對(duì)象作為參數(shù),并將其傳遞給其狀態(tài)類 _ArticleDetailPageState

      3. 定義 _ArticleDetailPageState 狀態(tài)類

      class _ArticleDetailPageState extends State<ArticleDetailPage> {
        late WebViewController _controller;
      
        @override
        void initState() {
          // TODO: implement initState
          _controller = WebViewController()
            ..setJavaScriptMode(JavaScriptMode.unrestricted)
            ..setBackgroundColor(const Color(0x00000000))
            ..loadRequest(Uri.parse(widget.article.url));
        }
      
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              title: Text(widget.article.title),
            ),
            body: WebViewWidget(controller: _controller),
          );
        }
      }
      
      初始化方法 initState
      @override
      void initState() {
        _controller = WebViewController()
          ..setJavaScriptMode(JavaScriptMode.unrestricted)
          ..setBackgroundColor(const Color(0x00000000))
          ..loadRequest(Uri.parse(widget.article.url));
      }
      
      • WebViewController 是用于控制 WebView 的控制器。
      • 使用級(jí)聯(lián)操作符 .. 連續(xù)調(diào)用多個(gè)方法:
        • setJavaScriptMode(JavaScriptMode.unrestricted):允許 WebView 執(zhí)行 JavaScript。
        • setBackgroundColor(const Color(0x00000000)):設(shè)置 WebView 的背景顏色為透明。
        • loadRequest(Uri.parse(widget.article.url)):加載文章的 URL。
      構(gòu)建方法 build
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.article.title),
          ),
          body: WebViewWidget(controller: _controller),
        );
      }
      
      • 使用 Scaffold 作為頁(yè)面的根布局,包含一個(gè)應(yīng)用欄 (AppBar) 和主體 (body)。
        • AppBar 顯示文章標(biāo)題。
        • WebViewWidget 使用之前初始化的 _controller 加載并顯示文章的網(wǎng)頁(yè)內(nèi)容。

      總結(jié)

      這段代碼實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的文章詳情頁(yè)面,通過 WebViewWidget 加載并顯示文章的網(wǎng)頁(yè)內(nèi)容。頁(yè)面的標(biāo)題是文章的標(biāo)題,主體部分是一個(gè) WebView,用于展示文章的網(wǎng)頁(yè)內(nèi)容。

      posted on 2025-02-14 15:26  愛吐水的小火龍  閱讀(69)  評(píng)論(0)    收藏  舉報(bào)

      主站蜘蛛池模板: 欧美z0zo人禽交另类视频| 男人和女人高潮做爰视频| 国产成人欧美一区二区三区在线| 国产午夜精品福利免费看| 无码av不卡免费播放| 亚洲国产精品一区二区久| 久久久久人妻精品一区三寸| 丰满岳乱妇久久久| 白河县| 国产欧洲欧洲久美女久久| 欧美白妞大战非洲大炮| 亚洲欧洲一区二区精品| 北岛玲中文字幕人妻系列| 国内精品视频一区二区三区| 中文在线天堂中文在线天堂| 亚洲欧美日韩久久一区二区| 亚洲暴爽av天天爽日日碰| 姚安县| 少妇高潮喷水正在播放| 国产精品一二二区视在线| 婷婷开心深爱五月天播播| 国产99久久精品一区二区| 好紧好爽午夜视频| 乱色老熟妇一区二区三区| 久久国产免费观看精品3| 亚洲精品国产中文字幕| 国产精品中文字幕二区| 亚洲精品色国语对白在线| 丁香婷婷在线观看| 亚洲精品福利一区二区三区蜜桃| 国产午夜A理论毛片| 蜜桃视频无码区在线观看| 青青青青久久精品国产| 欧美老少配性行为| 武强县| 99热久久这里只有精品| 无码人妻丰满熟妇区毛片18| 国产精品自在拍首页视频8| 亚洲一区中文字幕第十页| 海伦市| 亚洲嫩模喷白浆在线观看|