I have two tabs with a Default Tab bar. I have used Scoped-model for passing data between two tabs. When I insert data in one tab and press text Field again so that keyboard pops up but whole model gets reinitialized.
I have tried AutomaticKeepAliveClientMixin but no result. I have found out that every time I press the Text Field, keyBoard pops up and the Scoped model gets initialized. I have checked that by printing string in Scoped-Model constructor.
Here is my 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(),
],
),
),
),
),
);
}
}
Here is my FirstScreen which takes Name and Image as input and then inserts them in an 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.
);
}
}
Here is my SecondScreen which show the data in 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 ),
),
],
),
);
},
),
)));
}
}
Here is my PODO which
import 'dart:io' ;
class ModelProduct {
String name ;
File image ;
ModelProduct(this.name,this.image);
}
And lastly here is my Scoped-Model
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 ;
}
Widget build(BuildContext context) {
return ScopedModel<ProductsModel>(
model: ProductsModel(),
You've likely solved this by now but... this is your problem. You're initializing your model in the build method. It needs to be initialized outside of that.
For instance :
ProductsModel productsModel = ProductsModel();
Widget build(BuildContext context) {
return ScopedModel<ProductsModel>(
model: productsModel,