Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BloC store Model to Redux without being noticed if I call BloC event in Redux onInit #175

Open
ArnantoRizki opened this issue Apr 11, 2020 · 2 comments

Comments

@ArnantoRizki
Copy link

I use Redux to handle my globalstate, and BloC as localstate. I need to store my globalmodel in Redux to my BloC model on Redux onInit. I call BloC event in Redux onInit to get my BloC model same as globalmodel. But, I got my Redux model change even if I dont callback Redux update model methode when my BloC doing update model. But if I didn't call BloC event in Redux onInit, the model keep flow well. How I can handle this, so that my globalmodel didn't change when I update my BloC model?

this is my code:

import 'dart:async';
import 'package:kmb/redux/actions.dart';
import 'package:kmb/redux/global-model.dart';
import 'package:kmb/src/models/model-account.dart';
import 'package:kmb/src/views/settings-page/place-page/controller/place-bloc.dart';
import 'package:kmb/src/views/settings-page/place-page/signup-map-dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

class PlaceParent extends StatelessWidget {
@OverRide
Widget build(BuildContext context) {
return BlocProvider(
create: (context)=>PlaceBloc(),
child: PlacePage(),
);
}
}

class PlacePage extends StatefulWidget {
@OverRide
_PlacePageState createState() => _PlacePageState();
}

class _PlacePageState extends State {
TextEditingController addressCntrl = new TextEditingController();
Completer _controller = Completer();
final GlobalKey _scaffoldKey = new GlobalKey();
GlobalModel informasi;
PlaceBloc provider;
Set _marker = {};

GoogleMapController mapController;

@OverRide
void initState() {
super.initState();
informasi = GlobalModel.initState();
provider = BlocProvider.of(context);
}

@OverRide
void dispose() {
provider.close();
super.dispose();
}

@OverRide
Widget build(BuildContext context) {
return StoreConnector<GlobalModel,OnStoringInformationUpdatePointCallback>(
key: Key('StoreLocation'),
converter: (store)=>(informasiGlobal)=>(){
store.dispatch(ActionStoringInformation(informasi));
},
onInit: (stored){
print(stored.state.accountInfo.toMap());
informasi = stored.state;
provider.add(PlaceBlocEventStoreInit(informasi.accountInfo));
addressCntrl.text = stored.state.accountInfo.address;
},
onWillChange: (prevstate, nextstate){
print('prevs: $prevstate');
print('prevs: $nextstate');
},
builder: (context, callback){
return BlocListener<PlaceBloc, PlaceBlocModel>(
bloc: BlocProvider.of(context),
listener: (context, state){
if(!state.updateOnProccess){
if(state.updateOnFinish){
print('Masuk Sini CUK');
informasi.accountInfo.updatePoint(state.account);
callback(informasi);
Navigator.of(context).pop();
provider.add(PlaceBlocEventNormalize());
}
}
if(!state.updateLocOnProccess){
if(state.updateLocOnFinish){
addressCntrl.text = state.account.address;
mapController.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(
target: LatLng(state.account.pointLat, state.account.pointLon),
zoom: 16.0
)));
_marker.clear();
_marker.add(Marker(
markerId: MarkerId('001'),
position: LatLng(state.account.pointLat, state.account.pointLon)
));
provider.add(PlaceBlocEventNormalize());
}
}
},
child: BlocBuilder<PlaceBloc, PlaceBlocModel>(
builder: (context, state){
return Scaffold(
key: _scaffoldKey,
body: Container(
decoration: BoxDecoration(
color: Colors.white
),
child: Padding(
padding: const EdgeInsets.only(left:20.0, right:20.0),
child: ListView(
children: [
Divider(
color: Colors.transparent,
height: 30.0,
),
Row(
children: [
InkWell(
child: Icon(Icons.close),
onTap: (){
Navigator.of(context).pop();
},
),
VerticalDivider(
color: Colors.transparent,
width: 10.0,
),
Text('place Point', style: TextStyle(fontSize: 24.0),)
],
),
Divider(
color: Colors.transparent,
height: 20.0,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(5.0),
bottomRight: Radius.circular(5.0),
),
),
child: Column(
children: [
Container(
height: 200.0,
child: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(-6.1753924, 106.8249641),
zoom: 16.0
),
onMapCreated: (controller){
mapController = controller;
// if(state.account.pointLat!=null && state.account.pointLon!=null){
// mapController.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(
// target: LatLng(state.account.pointLat, state.account.pointLon),
// zoom: 16.0
// )));
// _marker.add(Marker(
// markerId: MarkerId('001'),
// position: LatLng(state.account.pointLat, state.account.pointLon)
// ));
// }
_controller.complete(controller);
},
markers: _marker,
),
),
Container(
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(5.0),
bottomRight: Radius.circular(5.0),
),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(16.0,10.0,16.0,10.0),
child: Container(
child: InkWell(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.launch, color: Colors.white, size: 32.0,),
VerticalDivider(
color: Colors.transparent,
width: 10.0,
),
Text('Open Map', style: TextStyle(color: Colors.white, fontSize: 16.0, fontWeight: FontWeight.w600),)
],
),
onTap: (){
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
print(state.account.pointLon);
return state.account.pointLon!=null? SignUpMapDialog(
currPositionLat: state.account.pointLat,
currPositionLon: state.account.pointLon,
onItemChoosed: (locparam){
provider.add(PlaceBlocEventStoreUpdateOnProcess());
provider.add(PlaceBlocEventStoreUpdate(Account(pointLat: locparam.pointLoc.latitude, pointLon: locparam.pointLoc.longitude, address: locparam.address)));
},
):SignUpMapDialog(
currPositionLat: -6.1753924,
currPositionLon: 106.8249641,
onItemChoosed: (locparam){
provider.add(PlaceBlocEventStoreUpdateOnProcess());
provider.add(PlaceBlocEventStoreUpdate(Account(pointLat: locparam.pointLoc.latitude, pointLon: locparam.pointLoc.longitude, address: locparam.address)));
},
);
}
);
},
),
),
),
)
],
),
),
Divider(
color: Colors.transparent,
height: 30.0,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Latitude', style: TextStyle(fontWeight: FontWeight.w600,fontSize: 16.0),),
Divider(height: 4.0, color: Colors.transparent,),
Text('${state.account.pointLat}', style: TextStyle(fontSize: 14.0, color: Colors.grey),),
],
),
Padding(
padding: const EdgeInsets.only(top:10.0, bottom:10.0),
child: Divider(height: 1.0, color: Colors.grey,),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Longitude', style: TextStyle(fontWeight: FontWeight.w600,fontSize: 16.0),),
Divider(height: 4.0, color: Colors.transparent,),
Text('${state.account.pointLon}', style: TextStyle(fontSize: 14.0, color: Colors.grey),),
],
),
Padding(
padding: const EdgeInsets.only(top:10.0, bottom:10.0),
child: Divider(height: 1.0, color: Colors.grey,),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Address', style: TextStyle(fontWeight: FontWeight.w600,fontSize: 16.0),),
Container(
child: TextFormField(
decoration: InputDecoration(
hintText: "Address",
),
controller: addressCntrl,
),
),
],
),
Divider(
color: Colors.transparent,
height: 30.0,
),
InkWell(
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.all(Radius.circular(5.0))
),
child: Padding(
padding: const EdgeInsets.fromLTRB(10.0,14.0,10.0,14.0),
child: Center(child: Text('Confirm', style: TextStyle(fontSize: 18.0, color: Colors.white, fontWeight: FontWeight.w700),)),
)
),
onTap: (){
provider.add(PlaceBlocEventUpdateRemoteOnProcess());
provider.add(PlaceBlocEventUpdateRemote(state.account));
},
),
Divider(
color: Colors.transparent,
height: 30.0,
),
],
),
),
),
);
}
)
);
}
);
}
}

typedef OnStoringInformationUpdatePointCallback = Function(GlobalModel informasiGlobal);

my Bloc code:
import 'dart:convert';
import 'package:bloc/bloc.dart';
import 'package:kmb/src/models/model-account.dart';
import 'package:kmb/src/services/api-serv.dart';
import 'package:equatable/equatable.dart';
import 'package:kmb/src/globals.dart' as globals;
import 'package:http/http.dart';

class PlaceBlocModel{
Account account;
bool onInit;
bool updateOnProccess;
bool updateOnFinish;
bool updateLocOnProccess;
bool updateLocOnFinish;

PlaceBlocModel({
this.account,
this.onInit,
this.updateOnProccess,
this.updateOnFinish,
this.updateLocOnFinish,
this.updateLocOnProccess
});

PlaceBlocModel.initState(){
this.account = Account.initState();
this.onInit = true;
this.updateOnProccess = false;
this.updateOnFinish = false;
this.updateLocOnProccess = false;
this.updateLocOnFinish = false;
}

void fromMapUpdate(Map<String, dynamic> map){
this.account.pointLat = map['data']['point_lat'];
this.account.pointLon = map['data']['point_lon'];
this.account.address = map['data']['address'];
this.account.token = map['token'];
}

void locUpdate(Account accountMap){
this.account.pointLat = accountMap.pointLat;
this.account.pointLon = accountMap.pointLon;
this.account.address = accountMap.address;
}

PlaceBlocModel.copy(PlaceBlocModel state){
this.account = state.account;
this.onInit = state.onInit;
this.updateOnProccess = state.updateOnProccess;
this.updateOnFinish = state.updateOnFinish;
this.updateLocOnProccess = state.updateLocOnProccess;
this.updateLocOnFinish = state.updateLocOnFinish;
}
}

abstract class PlaceBlocEvent extends Equatable{
@OverRide
List get props => [];
}
class PlaceBlocEventStoreInit extends PlaceBlocEvent{
final Account account;

PlaceBlocEventStoreInit(this.account);
}
class PlaceBlocEventStoreUpdate extends PlaceBlocEvent{
final Account account;

PlaceBlocEventStoreUpdate(this.account);
}
class PlaceBlocEventStoreUpdateOnProcess extends PlaceBlocEvent{}

class PlaceBlocEventUpdateRemoteOnProcess extends PlaceBlocEvent{}
class PlaceBlocEventUpdateRemote extends PlaceBlocEvent{
final Account account;

PlaceBlocEventUpdateRemote(this.account);
}
class PlaceBlocEventNormalize extends PlaceBlocEvent{}

class PlaceBloc extends Bloc<PlaceBlocEvent, PlaceBlocModel>{
@OverRide
PlaceBlocModel get initialState => PlaceBlocModel.initState();

@OverRide
Stream mapEventToState(PlaceBlocEvent event)async* {
if(event is PlaceBlocEventUpdateRemote){
print(event.account.toMapPlacePoint());
PlaceBlocModel retval = await PlacePointUpdate(event.account.toMapPlacePoint(), state);
yield retval;
}else if(event is PlaceBlocEventStoreInit){
if(state.onInit){
yield PlaceBlocModel(account: event.account, onInit: false, updateOnFinish: false, updateOnProccess: false, updateLocOnFinish: false, updateLocOnProccess: false);
}
}else if(event is PlaceBlocEventUpdateRemoteOnProcess){
yield PlaceBlocModel(account: state.account, onInit: false, updateOnFinish: false, updateOnProccess: true, updateLocOnFinish: state.updateLocOnFinish, updateLocOnProccess: state.updateLocOnProccess);
}else if(event is PlaceBlocEventStoreUpdateOnProcess){
yield PlaceBlocModel(account: state.account, onInit: false, updateOnFinish: state.updateOnFinish, updateOnProccess: state.updateOnProccess, updateLocOnFinish: false, updateLocOnProccess: true);
}else if(event is PlaceBlocEventStoreUpdate){
PlaceBlocModel currState = PlaceBlocModel.copy(state);
currState.locUpdate(event.account);
currState.updateLocOnFinish = true;
currState.updateLocOnProccess = false;
yield currState;
}else if(event is PlaceBlocEventNormalize){
yield PlaceBlocModel(account: state.account, onInit: false, updateOnFinish: false, updateOnProccess: false, updateLocOnFinish: false, updateLocOnProccess: false);
}
}

Future PlacePointUpdate(Map<String, dynamic> map, PlaceBlocModel state)async{
final Response response = await callApi(APIMethode.POST, globals.urlUpdatePlacePoint(), data: map);
if(response.statusCode == 200){
final jsonRes = json.decode(response.body);
if(jsonRes['error']==true){
return PlaceBlocModel(account: state.account, updateOnFinish: true, updateOnProccess: false);
}else{
print(map);
PlaceBlocModel Place = PlaceBlocModel.copy(state)..fromMapUpdate(jsonRes);
Place.updateOnFinish = true;
Place.updateOnProccess = false;
return Place;
}
}else{
return PlaceBlocModel(account: state.account, updateOnFinish: true, updateOnProccess: false);
}
}
}

@ArnantoRizki
Copy link
Author

ArnantoRizki commented May 7, 2020 via email

@raulccabreu
Copy link

Redux was built initialy over Flux architecture concept, to built Javascript apps, start with this: https://www.educative.io/blog/understanding-redux, and go on from there...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants