2017-07-30 10 views
1

Flutterを使用して単純なWikipediaブラウザを構築しています。ネイティブのFlutter Webviewがないので、手動で解析してHTMLフラグメントを同等のFlutterウィジェットに変換する必要があります。私はそうしましたが、いくつかのページを深く(青いリンクをクリックして)ナビゲートした後、ページ遷移のアニメーションは非常に遅くなりました。数ページ後にページ遷移が激しく遅くなる

再現手順:

は、次の依存関係

dependencies: 
    flutter: 
    sdk: flutter 
    fluro: "^1.1.0" 
    html: "^0.13.2" 

貼り付け]を追加し、(鮮明に観察するためにリリースモードで)次のコードを実行します。

import 'dart:async'; 
import 'dart:convert'; 

import 'package:flutter/gestures.dart'; 
import 'package:flutter/material.dart'; 
import 'package:http/http.dart' as http; 
import 'package:fluro/fluro.dart'; 
import 'package:html/dom.dart' as DOM; 
import 'package:html/parser.dart' show parse; 

void main() { 
    runApp(new MyApp()); 
} 

class MyApp extends StatefulWidget { 
    @override 
    _MyAppState createState() => new _MyAppState(); 
} 

class _MyAppState extends State<MyApp> { 
    final router = new Router(); // Fluro router 

    @override 
    void initState() { 
    super.initState(); 
    router.define(
     '/wiki', 
     handler: new Handler(
     handlerFunc: (_, params) => new WikiPage(title: params['q']) 
    ) 
    ); 
    } 

    @override 
    Widget build(BuildContext context) { 
    return new MaterialApp(
     title: 'Flutter Demo', 
     theme: new ThemeData(
     primarySwatch: Colors.blue, 
    ), 
     onGenerateRoute: router.generator, // delegate to Fluro 
     routes: { 
     '/': (BuildContext context) => new WikiPage(title: 'Firefox') 
     }, 
    ); 
    } 
} 

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

    @override 
    _WikiPageState createState() => new _WikiPageState(); 
} 

class _WikiPageState extends State<WikiPage> { 

    @override 
    void initState() { 
    super.initState(); 
    } 

    @override 
    Widget build(BuildContext context) { 
    return new Scaffold(
     appBar: new AppBar(title: new Text(widget.title)), 
     body: new FutureBuilder<String>(
     future: getPage(widget.title), 
     builder: (context, snapshot) { 
      if (snapshot.hasError) return new Text('Error: ${snapshot.error}'); 
      if (snapshot.hasData) { 
      if (snapshot.data.isEmpty) return new Container(); // empty result 

      // parse HTML 
      DOM.Document document = parse(snapshot.data); 
      document.querySelector('.infobox')?.remove(); // remove the infobox table 
      List<DOM.Element> paragraphs = document.getElementsByTagName('p'); 

      // convert HTML tree to Flutter widgets 
      return new ListView(
       padding: const EdgeInsets.all(16.0), 
       children: paragraphs.map((paragraph) => 
       new RichText(
        text: new TextSpan(
        text: '', 
        style: DefaultTextStyle.of(context).style, 
        children: paragraph.nodes.map((node) { 
         if (node.toString() == '<html a>') { // HTML <a> tag 
         String href = node.attributes['href']; 
         return new TextSpan(// as blue link 
          text: node.text, 
          style: Theme.of(context).textTheme.body1.copyWith(
          color: Colors.blue 
         ), 
          recognizer: new TapGestureRecognizer() 
          ..onTap =() => Navigator.of(context).pushNamed(
           '/wiki?q=${href.split('/')[2]}' 
          ) 
         ); 
         } else { 
         return new TextSpan(text: node.text); 
         } 
        }).toList() 
       ) 
       ) 
      ).toList() 
      ); 

      } else { // waiting for data 
      return new Center(child: new CircularProgressIndicator()); 
      } 
     }, 
    ) 
    ); 
    } 

    Future<String> getPage(String title) async { 
    final String url = 'https://en.wikipedia.org/w/api.php?' + 
    'action=mobileview&format=json&sections=0&noimages=1&noheadings=1' + 
    '&formatversion=2&page=${Uri.encodeComponent(title)}'; 

    final response = await http.get(url); 
    final json = JSON.decode(response.body); 
    return json['mobileview']['sections'][0]['text']; // retrieve HTML string 
    } 
} 
  1. ナビゲートするために青色のWikipediaのリンクのいずれかをクリックしてください。最初はページ遷移アニメーション(最初の2〜3ページ)がスムーズです。新しいページが下から挿入されます(Androidプラットフォーム)。
  2. しかし、各ナビゲーションでページ遷移がぎくしゃくしくなり、しばらくの間フリーズするまで(ボトムアップページ遷移は完全になくなっています)。

何が問題なのですか?ガベージコレクタの問題?どんな助けもありがとうございます。

[√] Flutter (on Microsoft Windows [Version 10.0.15063], locale en-US, channel master) 
    • Flutter at C:\Users\tzm\Downloads\flutter_sdk 
    • Framework revision 6655074b37 (2 days ago), 2017-07-28 15:44:38 -0700 
    • Engine revision 232f4636e5 
    • Tools Dart version 1.25.0-dev.7.0 
+0

あなたは常に気分が悪いアプリです。あなたがウェブページ全体を解析している間にウィジェットを構築しているので、不気味さが気になります。おそらく、あなたはウィジェットが解析された後にページをロードするだけでしょうか? いずれにしても、私はwikipedia flutterプロジェクトを発見しました。github.com/namiwang/wiki-flutterここでは、flutter pub.dartlang.org/packages/flutter_webview_pluginの統合されていないWebビューがあります - user1462442 7分前 – user1462442

+0

@ user1462442私は確信していますボトルネックは解析ではありません。最初の数ページの読み込みは非常にスムーズですが、より多くのMaterialPageRoutesをナビゲータにプッシュするにつれて徐々に重くなります。 –

+0

最初のページにアニメーションが動きます。 – user1462442

答えて

0

解決策が見つかりました。トリックは、ダートアイソレートを使用して別のスレッドに高価なHTMLパーシングをオフロードすることです

  • maintainStateをMaterialPageRouteからfalseに設定すると、以前の計算は常にメモリから破棄されます。欠点は、現在のページからポップアップして以前に訪れたページを再生成する必要があることです。
関連する問題