У меня есть две вкладки с панелью вкладок по умолчанию.Я использовал Scoped-модель для передачи данных между двумя вкладками.Когда я вставляю данные в одну вкладку и снова нажимаю текстовое поле, чтобы всплыла клавиатура, но вся модель была повторно инициализирована.
Я пробовал AutomaticKeepAliveClientMixin, но безрезультатно.Я обнаружил, что каждый раз, когда я нажимаю текстовое поле, всплывающее окно-клавиатура всплывает, и модель Scoped инициализируется.Я проверил это, напечатав строку в конструкторе Scoped-Model.
Вот мой TabView
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:basicflutter/tabs/FirstScreen.dart';
import 'package:basicflutter/tabs/SecondScreen.dart';
import 'package:basicflutter/models/product.dart';
import 'package:basicflutter/scopedModel/addproduct.dart';
import 'package:scoped_model/scoped_model.dart';
class MyTabs extends StatelessWidget {
static String tag = 'tab-page';
@override
Widget build(BuildContext context) {
return ScopedModel<ProductsModel>(
model: ProductsModel(),
child: MaterialApp(
home: DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
],
),
title: Text('Flutter Tabs Example'),
),
body: TabBarView(
children: [
FirstScreen(),
SecondScreen(),
],
),
),
),
),
);
}
}
Вот мой FirstScreen, который принимает имя и изображение в качестве входных данных, а затем вставляет их в ArrayList
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:basicflutter/tabs/SecondScreen.dart';
import 'package:basicflutter/models/product.dart';
import 'package:basicflutter/scopedModel/addproduct.dart';
import 'package:scoped_model/scoped_model.dart';
class FirstScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen>
with AutomaticKeepAliveClientMixin<FirstScreen> {
File _image;
final NameController = TextEditingController();
@override
void initState() {
super.initState();
print("InitState called") ;
}
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
final ProductName = TextFormField(
controller: NameController,
autofocus: false,
obscureText: false,
decoration: InputDecoration(
hintText: 'Prodcut Name',
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
final AddProduct = Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Column(
children: <Widget>[
ScopedModelDescendant<ProductsModel>(
rebuildOnChange: false,
builder: (context, child, model) => Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
onPressed: (){
ModelProduct newProduct = ModelProduct(NameController.text,_image);
model.AddNewProduct(newProduct) ;
setState(() {
NameController.clear();
_image = null ;
});
},
padding: EdgeInsets.all(12),
color: Colors.lightBlueAccent,
child: Text('Add product', style: TextStyle(color: Colors.white)),
),
)
)
],
),
);
Future getImage() async {
var taken_image = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
_image = taken_image;
});
}
return Scaffold(
body: GestureDetector(
onTap: (){FocusScope.of(context).requestFocus(new FocusNode());},
child: Container(
padding: EdgeInsets.all(20),
child: new ListView(
children: [
SizedBox(height: 20.0),
Text(
'Add your product here',
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
SizedBox(height: 20.0),
ProductName,
SizedBox(height: 20.0),
_image == null
? Center(
child: new Container(
padding: EdgeInsets.all(20),
child: Text('No image selected.')))
: Image.file(_image),
SizedBox(
height: 20.0,
),
AddProduct,
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: getImage,
child: Icon(Icons.camera),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Вот мой SecondScreenкоторые показывают данные в ListView
import 'package:flutter/material.dart';
import 'package:basicflutter/tabs/FirstScreen.dart';
import 'package:basicflutter/models/product.dart';
import 'package:basicflutter/scopedModel/addproduct.dart';
import 'package:scoped_model/scoped_model.dart';
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new ScopedModelDescendant<ProductsModel>(
builder: (context, child, model) => Container(
child: new ListView.builder(
itemCount: model.count,
itemBuilder: (BuildContext context, int index) {
return new Card(
child: Column(
children: <Widget>[
Text(model.GetAllProducts[index].name),
Container(
width: 250.0,
height: 250.0,
alignment: Alignment.center,
child:
model.GetAllProducts[index].image == null
? Center(
child: new Container(
padding: EdgeInsets.all(20),
child: Text('No image selected.')))
: Image.file(model.GetAllProducts[index].image ),
),
],
),
);
},
),
)));
}
}
Вот мой PODO, который
import 'dart:io' ;
class ModelProduct {
String name ;
File image ;
ModelProduct(this.name,this.image);
}
И, наконец, вот моя Scoped-модель
import 'package:flutter/material.dart';
import 'package:basicflutter/tabs/FirstScreen.dart';
import 'package:basicflutter/tabs/SecondScreen.dart';
import 'package:basicflutter/models/product.dart';
import 'package:basicflutter/scopedModel/addproduct.dart';
import 'package:scoped_model/scoped_model.dart';
import 'dart:io';
class ProductsModel extends Model {
final List<ModelProduct> productList = List<ModelProduct>();
ProductsModel(){
print("ProductsModel init") ;
}
void AddNewProduct(ModelProduct p) {
productList.add(p);
notifyListeners() ;
print(this.count);
}
int get count => productList.length ;
List<ModelProduct> get GetAllProducts => productList ;
}