質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

Q&A

解決済

2回答

1699閲覧

OGP(メタデータ)を用いたwebサイト一覧アプリの実装

Daisan_gen

総合スコア0

Flutter

Flutterは、iOSとAndroidのアプリを同じコードで開発するためのフレームワークです。オープンソースで開発言語はDart。双方のプラットフォームにおける高度な実行パフォーマンスと開発効率を提供することを目的としています。

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

Dart

Dartは、Googleによって開発されたJavaScriptの代替となることを目的に作られた、ウェブ向けのプログラミング言語である。

0グッド

0クリップ

投稿2021/07/05 15:50

前提・実現したいこと

複数のURLからメタデータを取得し、'タイトル'、'サムネ'、'概要'をまとめたwebサイト一覧を作りたい。
具体的には、ニュースアプリなどの記事一覧のイメージです。

現在、for文を用いてメタデータ取得と格納をURL毎に行いましたが、
メタデータ用のList内に要素が入っていないようで、アプリ上に何も表示されません。

for文がアプリ起動時に機能してないのだと予想していますが、
解決策がわからなかったので教えていただきたいです。

発生している問題・エラーメッセージ

エラーメッセージはありません。

該当のソースコード

Flutter

1 2class articleListPanel extends StatelessWidget { 3 articleListPanel(this._URL); 4 final List<String> _URL; 5 6 @override 7 Widget build(BuildContext context) { 8 ///個別での動作確認用 9 //final watchMetadata = context.watch<MetadataModel>().fetchOgpFrom(_URL[0]); 10 //Metadata _ogp = context.select((MetadataModel _model) => _model.ogp); 11 ///OGP(Metadata)をList化して管理 12 List<Metadata> _OGP = [];//←ここにメタデータまとめたい 13 void setOgp () { 14 for (var i = 0; i < _URL.length; i++) { 15 final watchMetadata = context.watch<MetadataModel>().fetchOgpFrom(_URL[i]); 16 Metadata _ogp = context.select((MetadataModel _model) => _model.ogp); 17 _OGP.add(_ogp); 18 } 19 } 20 21 return ListView.builder( 22 itemCount: _OGP.length, 23 itemBuilder: (context,n){ 24 return Container( 25 height: 150, 26 //color: Colors.green[200], 27 child: Row( 28 mainAxisAlignment: MainAxisAlignment.spaceBetween, 29 crossAxisAlignment: CrossAxisAlignment.start, 30 children: [ 31 Flexible( 32 child: Container( 33 width: double.maxFinite, 34 height: double.maxFinite, 35 margin: const EdgeInsets.all(2), 36 child: Text( 37 _OGP[n].title ?? "No title",style: const TextStyle( 38 fontWeight: FontWeight.bold,fontSize: 24), 39 ),),), 40 ] 41 ), 42 );} 43 ); 44 45 } 46}

Flutter

1Map<String, dynamic> _ogp = { 2 "title": null, 3 "image": null, 4 "description":null, 5}; 6 7class MetadataModel extends ChangeNotifier { 8 Metadata ogp = Metadata.fromJson(_ogp); 9 10 void fetchOgpFrom(String _url) async { 11 final response = await http.get(Uri.parse(_url)); 12 final document = MetadataFetch.responseToDocument(response); 13 ogp = MetadataParser.openGraph(document); 14 notifyListeners(); 15 } 16}

試したこと

メタデータ格納用のList"_OGP"を作成し、for文を用いて取得したメタデータを格納しました。
for文使わず、~.fetchOgpFrom(_URL[0])部の数字手入力した場合は機能します。

補足情報(FW/ツールのバージョンなど)

開発ツールのバージョン情報は以下になります。
Flutter 2.3.0-17.0.pre.225 • channel master • https://github.com/flutter/flutter.git
Tools • Dart 2.14.0 (build 2.14.0-182.0.dev)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

bool _loading;
@override
void initState(){
super.initState();
_loading = true; //ロード開始
_getOgpData();
}

_getOgpData() async{
await setOgp();
setState(() {
_loading = false;
});
}

非同期なのでこれを追加してみてはどうでしょうか
すみません間違い訂正しました。
var -> bool

投稿2021/07/07 12:39

編集2021/07/08 02:22
endiv

総合スコア161

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Daisan_gen

2021/07/07 14:08

ありがとうございます! 非同期処理についてはよくわかっていなかったので、提示していただいたコードをもとに色々調べながらやってみます!
Daisan_gen

2021/07/24 08:30

リアクション遅くなってごめんなさい。 提示していただいたコードを組み込んでみましたが、リストが更新され続けるような状態になり、思った動きをしてもらえませんでした。(おそらく、setState()が常に更新され続けるプログラムになってしまった) 別の方法を調べてみたところ、親ウィジェットで下記のように記載することで想像した動作になりました。 ChangeNotifierProvider(create: (context) => MetadataModel(_URL)..fetchOgpFrom() 詳細は別途記載しますが、画面遷移する段階で情報の格納を終わらせるようにしました。 (元のコードは画面遷移した先で情報の格納を行おうとしていた) setStateやinitStateについて勉強する良いきっかけになりました。ありがとうございます。
guest

0

自己解決

ArticleLists クラスからURLを MetadataModelクラスとarticleListPanelクラスに譲渡する。ChangeNotifierProviderでMetadataModelクラスをcreateする際に、'..メソッド()'を追加することで、画面が切り替わる際にメソッド処理を完了させる。(このときにfor文が回るようにした) articleListPanelクラスでは、すでに完了したメソッドから要素を持ってくることで状態の更新が行われなくなり、記事一覧が更新され続けることは無くなった。

Dart

1class ArticleLists extends StatelessWidget { 2 //headerに表示される名前 3 final String screenName = '記事一覧'; 4 5 //url一覧暫定 6 final List<String> _URL = [ 7 /// 参考記事のURLを記載 8 ]; 9 10 11 Widget build(BuildContext context) { 12 return Scaffold( 13 appBar: Header(headerTitle: screenName), 14 body: Scrollbar( 15 child: ChangeNotifierProvider( 16 create: (context) => MetadataModel(_URL)..fetchOgpFrom(), 17 child: articleListPanel(_URL)) 18 ), 19 ); 20 } 21} 22

Dart

1/// 画面遷移時にデータ格納を行う。 2class MetadataModel extends ChangeNotifier { 3 MetadataModel(this._url); 4 final List<String> _url; 5 6 List<Metadata> docs = []; //外部から参照するためのまとめ 7 List<Metadata> _docs = []; // データ格納 8 9 ///URL毎にdataの格納を行う。 10 Future fetchOgpFrom() async { 11 for (int i = 0; i< _url.length; i++) { 12 final response = await http.get(Uri.parse(_url[i])); 13 final document = MetadataFetch.responseToDocument(response); 14 var ogp = MetadataParser.openGraph(document); 15 this._docs.add(ogp); 16 } 17 this.docs = _docs; 18 notifyListeners(); 19 } 20}

Dart****

1 2import 'package:flutter/material.dart'; 3import 'package:list_view_ogp/model/commonaly/get_meta_data.dart'; 4import 'package:metadata_fetch/metadata_fetch.dart'; 5import 'package:provider/provider.dart'; 6 7 8class articleListPanel extends StatefulWidget { 9 articleListPanel(this._URL); 10 final List<String> _URL; 11 12 13 State<articleListPanel> createState() => _articleListPanelState(); 14} 15 16class _articleListPanelState extends State<articleListPanel> { 17 List<Metadata> _UrlInfo =[]; 18 19 Widget build(BuildContext context) { 20 return ListView.builder( 21 itemCount: widget._URL.length, 22 itemBuilder: (context,n){ 23 return Builder( 24 builder: (context) { 25 final mydata = Provider.of<MetadataModel>(context); 26 _UrlInfo = mydata.docs; 27 final item = _UrlInfo[n]; 28 return Container( 29 height: 150, 30 child: Row( 31 mainAxisAlignment: MainAxisAlignment.spaceBetween, 32 crossAxisAlignment: CrossAxisAlignment.start, 33 children: [ 34 Flexible( 35 child: Container( 36 width: double.maxFinite, 37 height: double.maxFinite, 38 margin: const EdgeInsets.all(2), 39 child: Text( 40 item.title 41 ?? "No title", 42 style: const TextStyle(fontWeight: FontWeight.bold,fontSize: 24), 43 ) 44 ) 45 ) 46 ] 47 ), 48 ); 49 } 50 );} 51 ); 52 53 } 54} 55

投稿2021/07/24 09:00

Daisan_gen

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問