Flutterページ間のデータ転送(共有)のいくつかの一般的な方法
14374 ワード
前言
Androidでは、ページジャンプ(Frament,Activity)の際に、現在のデータの一部を別のページに持ち込み、別のページで使用するシーンがよくあります.この時、私たちがよく使うのはIntent、Bundleなどの携帯データです.
では、Flutterの開発過程では、ページ間のデータ伝達も欠かせないし、あるページのデータをどのように別のページに伝達(共有)するか、あるいは現在のページを閉じて前のページにデータを与えるか.
この記事では、Flutterでページ間のデータ転送(共有)の一般的な方法とシーンについて説明します.
データ転送を開始する前に、データを転送するクラスを作成します.
Androidでオブジェクトを渡すにはシーケンス化が必要です
データの伝達方法を具体的に見てみましょう
コンストラクタによるデータの転送
コンストラクタによるデータの転送は最も簡単な方法であり、最も一般的な方法でもあります.最初のページでは、データの転送が必要なオブジェクトをシミュレートして作成します.ジャンプをクリックすると、DataTransferByConstructorPageページにデータを渡し、持参したデータをページに表示します.転送データオブジェクト を作成する. DataTransferByConstructorPageページにジャンプする方法 を定義する DataTransferByConstructorPageページでデータを受信して表示します.コードは次のとおりです.
私たちは2つのことをする必要があります.
1.final変数
2.コンストラクタ受信パラメータ
1ページが閉じると前のページにデータを運ぶ(Navigator.pop)
Android開発では、前のページにデータを渡すために一般的に使用されている従来の方法はstartActivity ForResult()メソッドです.しかしflutterではそんなに面倒なことはありません.Navigatorを使うだけですpopメソッドはデータ結果を持ち帰ることができます.しかし、私たちがジャンプするときは2つの点に注意する必要があります.
1.返された結果を受信するための非同期メソッドを定義する必要があります.
2.閉じるページでNavigatorを使用します.popは最初のページに戻ります
InheritedWidget方式
公式サイトの説明:InheritedWidgetはFlatterの中で非常に重要な機能型Widgetであり、Widgetツリーでデータを効率的に下に伝達し、共有することができ、これはWidgetツリーでデータを共有する必要があるシーンで非常に便利であり、例えばFlatterでは、InheritedWidgetを通じてアプリケーショントピック(Theme)とLocle(現在の言語環境)の情報を共有している.
InheritedWidgetはReactのcontextと同様に機能しており、逐次転送と比較してコンポーネントの階層間転送を実現します.InheritedWidgetのWidgetツリーでのデータ転送方向は上から下であり、これはNotificationの転送方向とは正反対である.
利点:各Widgetを制御して単独でデータを取り出して使用できる
1ページに同じレベルのWeigetしか存在しない場合、コンストラクタを使用する方法はもちろん最も簡単で、最も便利ですが、1ページに複数のレベルのWeigetが存在する場合、コンストラクタの方法に限界があります.この場合、InheritedWidgetを使用するのが良い選択です. InheritedWidgetを継承するデータソース を提供する.ページジャンプ時にデータを携帯する方法 を定義する.ページにジャンプし、データコードを示す
上の
1.修正後のProviderクラスは以下の通りです.
2.ジャンプを使用する場合の修正コードは以下の通りです(主に汎用サポートの追加)
伝達された値を受信する方法は次のとおりです.
IGenericDataProvider.of(context)は直接値をとることができる
グローバルなデータ提供方法
この方法では、InheritedWidgetを使用します.違いは、ジャンプするときにIGenericDataProviderを作成することではありません.彼を最上階に置くのです
注意:この方法では、データを最上位に配置する必要があります.
最上位データの定義
データの受信方法の基本と
final data = IGenericDataProvider.of(context)、データの取得
グローバル・シングル・インスタンス・モードでの使用
この方法は、グローバルな単一のインスタンスオブジェクトを作成し、どこでもこのオブジェクトを操作し、このオブジェクトを格納し、値を取得することができます.
単一オブジェクト を作成する.
は、一例のオブジェクトにデータ を格納する.
は、伝達する値 を受信して使用する.
グローバル・シングル・インスタンスとStreamを組み合わせたデータの転送グローバルを受け入れる単一のオブジェクトを作成し、伝達値をStream方式 に変換する.受信データは、StreamBuilderを用いて直接受信処理することができる .
携帯するデータを渡す
は、伝達する値 を受信する.
まとめ
以上、Flutterでよく使用されるいくつかのページ間でデータを転送する方法について説明しましたが、最後の方法は
現在公式に推奨されているproviderは、実際には
以上はページ間の値の伝達の1つの総括で、本文Demo、もし書く不足な点があるならば、指摘して~
Androidでは、ページジャンプ(Frament,Activity)の際に、現在のデータの一部を別のページに持ち込み、別のページで使用するシーンがよくあります.この時、私たちがよく使うのはIntent、Bundleなどの携帯データです.
では、Flutterの開発過程では、ページ間のデータ伝達も欠かせないし、あるページのデータをどのように別のページに伝達(共有)するか、あるいは現在のページを閉じて前のページにデータを与えるか.
この記事では、Flutterでページ間のデータ転送(共有)の一般的な方法とシーンについて説明します.
データ転送を開始する前に、データを転送するクラスを作成します.
Androidでオブジェクトを渡すにはシーケンス化が必要です
Serializable
またはParcelable
インタフェースを転送することができ、Flutterではデータ転送にシーケンス化された方法がなく、直接オブジェクトを転送することができます.単純なクラスを定義するには、次のようにします.///
class TransferDataEntity {
String name;
String id;
int age;
TransferDataEntity(this.name, this.id, this.age);
}
データの伝達方法を具体的に見てみましょう
コンストラクタによるデータの転送
コンストラクタによるデータの転送は最も簡単な方法であり、最も一般的な方法でもあります.最初のページでは、データの転送が必要なオブジェクトをシミュレートして作成します.ジャンプをクリックすると、DataTransferByConstructorPageページにデータを渡し、持参したデータをページに表示します.
final data = TransferDataEntity("001", " ", 18);
_transferDataByConstructor(BuildContext context, TransferDataEntity data) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DataTransferByConstructorPage(data: data)));
}
私たちは2つのことをする必要があります.
1.final変数
final TransferDataEntity data
を提供する2.コンストラクタ受信パラメータ
DataTransferByConstructorPage({this.data});
を提供する///
class DataTransferByConstructorPage extends StatelessWidget {
final TransferDataEntity data;
DataTransferByConstructorPage({this.data});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(" "),
),
body: Column(
children: [
Container(
width: double.infinity,
height: 40.0,
alignment: Alignment.center,
child: Text(data.id),
),
Container(
width: double.infinity,
height: 40.0,
alignment: Alignment.center,
child: Text(data.name),
),
Container(
width: double.infinity,
height: 40.0,
alignment: Alignment.center,
child: Text("${data.age}"),
)
],
),
);
}
}
1ページが閉じると前のページにデータを運ぶ(Navigator.pop)
Android開発では、前のページにデータを渡すために一般的に使用されている従来の方法はstartActivity ForResult()メソッドです.しかしflutterではそんなに面倒なことはありません.Navigatorを使うだけですpopメソッドはデータ結果を持ち帰ることができます.しかし、私たちがジャンプするときは2つの点に注意する必要があります.
1.返された結果を受信するための非同期メソッドを定義する必要があります.
/// dataFromOtherPage
_toTransferForResult(BuildContext context, TransferDataEntity data) async {
final dataFromOtherPage = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => TransferRouterPage(data: data)),
) as TransferDataEntity;
}
2.閉じるページでNavigatorを使用します.popは最初のページに戻ります
//
_backToData(BuildContext context){
var transferData = TransferDataEntity(" ","007",20);
Navigator.pop(context,transferData);
}
InheritedWidget方式
公式サイトの説明:InheritedWidgetはFlatterの中で非常に重要な機能型Widgetであり、Widgetツリーでデータを効率的に下に伝達し、共有することができ、これはWidgetツリーでデータを共有する必要があるシーンで非常に便利であり、例えばFlatterでは、InheritedWidgetを通じてアプリケーショントピック(Theme)とLocle(現在の言語環境)の情報を共有している.
InheritedWidgetはReactのcontextと同様に機能しており、逐次転送と比較してコンポーネントの階層間転送を実現します.InheritedWidgetのWidgetツリーでのデータ転送方向は上から下であり、これはNotificationの転送方向とは正反対である.
利点:各Widgetを制御して単独でデータを取り出して使用できる
1ページに同じレベルのWeigetしか存在しない場合、コンストラクタを使用する方法はもちろん最も簡単で、最も便利ですが、1ページに複数のレベルのWeigetが存在する場合、コンストラクタの方法に限界があります.この場合、InheritedWidgetを使用するのが良い選択です.
InheritedWidget
方式を使用するには、次の手順に従います.class IDataProvider extends InheritedWidget{
final TransferDataEntity data;
IDataProvider({Widget child,this.data}):super(child:child);
@override
bool updateShouldNotify(IDataProvider oldWidget) {
return data!=oldWidget.data;
}
static IDataProvider of(BuildContext context){
return context.inheritFromWidgetOfExactType(IDataProvider);
}
}
/// IDataWidget
_inheritedToPage(BuildContext context, TransferDataEntity data) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => IDataProvider(
child: IDataWidget(),
data: data,
)));
}
class IDataWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final data = IDataProvider.of(context).data;
return Scaffold(
appBar: AppBar(
title: Text("Inherited "),
),
body: Column(
children: [
Container(
alignment: Alignment.center,
height: 40.0,
child: Text(data.name),
),
Container(
alignment: Alignment.center,
height: 40.0,
child: Text(data.id),
),
Container(
alignment: Alignment.center,
height: 40.0,
child: Text("${data.age}"),
),
IDataChildWidget()
],
),
);
}
}
class IDataChildWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final data = IDataProvider.of(context).data;
return Container(
child: Text(data.name),
);
}
}
上の
IDataProvier
を改造して汎用型に加えれば通用します1.修正後のProviderクラスは以下の通りです.
class IGenericDataProvider extends InheritedWidget {
final T data;
IGenericDataProvider({Key key, Widget child, this.data})
: super(key: key, child: child);
@override
bool updateShouldNotify(IGenericDataProvider oldWidget) {
return data != oldWidget.data;
}
static T of(BuildContext context) {
return (context.inheritFromWidgetOfExactType(
IGenericDataProvider().runtimeType) as IGenericDataProvider).data;
}
}
2.ジャンプを使用する場合の修正コードは以下の通りです(主に汎用サポートの追加)
_inheritedGenericToPage(BuildContext context, TransferDataEntity data) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => IGenericDataProvider(
child: IDataWidget(),
data: data,
)));
}
伝達された値を受信する方法は次のとおりです.
IGenericDataProvider.of(context)は直接値をとることができる
class IGenericDataWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final data = IGenericDataProvider.of(context);
return Scaffold(
appBar: AppBar(
title: Text("Inherited "),
),
body: Column(
children: [
Container(
alignment: Alignment.center,
height: 40.0,
child: Text(data.name),
),
Container(
alignment: Alignment.center,
height: 40.0,
child: Text(data.id),
),
Container(
alignment: Alignment.center,
height: 40.0,
child: Text("${data.age}"),
),
],
),
);
}
}
グローバルなデータ提供方法
この方法では、InheritedWidgetを使用します.違いは、ジャンプするときにIGenericDataProviderを作成することではありません.彼を最上階に置くのです
注意:この方法では、データを最上位に配置する必要があります.
最上位データの定義
class MyApp extends StatelessWidget {
// This widget is the root of your application.
//
var params = InheritedParams();
@override
Widget build(BuildContext context) {
return IGenericDataProvider(
data: params,
child: MaterialApp(
title: 'Data Transfer Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Data Transfer Demo'),
),
);
}
}
データの受信方法の基本と
InheritedWidget
同じfinal data = IGenericDataProvider.of(context)、データの取得
class InheritedParamsPage extends StatefulWidget {
@override
_InheritedParamsPageState createState() => _InheritedParamsPageState();
}
class _InheritedParamsPageState extends State {
@override
Widget build(BuildContext context) {
final data = IGenericDataProvider.of(context);
return Scaffold(
appBar: AppBar(
title: Text(" "),
),
body:Column(
children: [
Container(
alignment: Alignment.center,
height: 40.0,
child: Text(data.name),
),
Container(
alignment: Alignment.center,
height: 40.0,
child: Text(data.id),
),
Container(
alignment: Alignment.center,
height: 40.0,
child: Text("${data.age}"),
),
],
),
);
}
}
グローバル・シングル・インスタンス・モードでの使用
この方法は、グローバルな単一のインスタンスオブジェクトを作成し、どこでもこのオブジェクトを操作し、このオブジェクトを格納し、値を取得することができます.
class TransferDataSingleton {
static final TransferDataSingleton _instanceTransfer =
TransferDataSingleton.__internal();
TransferDataEntity transData;
factory TransferDataSingleton() {
return _instanceTransfer;
}
TransferDataSingleton.__internal();
}
final transSingletonData = TransferDataSingleton();
_singletonDataTransfer(BuildContext context) {
var transferData = TransferDataEntity(" ", "002", 25);
transSingletonData.transData = transferData;
Navigator.push(context,
MaterialPageRoute(builder: (context) => TransferSingletonPage()));
}
class TransferSingletonPage extends StatefulWidget {
@override
_TransferSingletonPageState createState() => _TransferSingletonPageState();
}
class _TransferSingletonPageState extends State {
@override
Widget build(BuildContext context) {
//
var data = transSingletonData.transData;
return Scaffold(
appBar: AppBar(
title: Text(" "),
),
body: Column(
children: [
Container(
alignment: Alignment.center,
height: 40.0,
child: Text(data.name),
),
Container(
alignment: Alignment.center,
height: 40.0,
child: Text(data.id),
),
Container(
alignment: Alignment.center,
height: 40.0,
child: Text("${data.age}"),
),
],
),
);
}
}
グローバル・シングル・インスタンスとStreamを組み合わせたデータの転送
class TransferStreamSingleton {
static final TransferStreamSingleton _instanceTransfer =
TransferStreamSingleton.__internal();
StreamController streamController;
void setTransferData(TransferDataEntity transData) {
streamController = StreamController();
streamController.sink.add(transData);
}
factory TransferStreamSingleton() {
return _instanceTransfer;
}
TransferStreamSingleton.__internal();
}
final streamSingletonData = TransferStreamSingleton();
_streamDataTransfer(BuildContext context) {
var transferData = TransferDataEntity(" ", "005", 20);
streamSingletonData.setTransferData(transferData);
Navigator.push(context,
MaterialPageRoute(builder: (context) => TransferStreamPage()));
}
class TransferStreamPage extends StatefulWidget {
@override
_TransferStreamPageState createState() => _TransferStreamPageState();
}
class _TransferStreamPageState extends State {
StreamController _streamController = streamSingletonData.streamController;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(" Stream"),
),
body: StreamBuilder(
stream: _streamController.stream,
initialData: TransferDataEntity("", "", 0),
builder: (context, snapshot) {
return Column(
children: [
Container(
alignment: Alignment.center,
height: 40.0,
child: Text(snapshot.data.name),
),
Container(
alignment: Alignment.center,
height: 40.0,
child: Text(snapshot.data.id),
),
Container(
alignment: Alignment.center,
height: 40.0,
child: Text("${snapshot.data.age}"),
),
],
);
}));
}
@override
void dispose() {
_streamController.close();
super.dispose();
}
}
まとめ
以上、Flutterでよく使用されるいくつかのページ間でデータを転送する方法について説明しましたが、最後の方法は
Stream
およびStreamBuilder
専門的な記事がありますFlutter
Stream
. Flutter Streamの概要と使用の詳細についてStream
および一部の操作の使用.現在公式に推奨されているproviderは、実際には
InheritedWidget
を使用しています.時間があれば、InheritedWidget
と使用方法を詳しくお勧めします.以上はページ間の値の伝達の1つの総括で、本文Demo、もし書く不足な点があるならば、指摘して~