class Brain with ChangeNotifier {
List<List<IconData>> icon = [];
Brain() {
for (int i = 0; i < 10; i++) {
List<IconData> temp = [];
for (int j = 0; j < 10; j++) {
temp.add(Icons.square_outlined);
}
icon.add(temp);
}
[...]
}
}
After some testing it seems like provider is calling it's constructor every widget state, but my icon list doesn't reset after changing some of the icons. How is it possible?
Well you need to use notifyListeners(); when you need to refresh your Ui, use it at the end of your Brain constructor after your process finished and see the result
Brain() {
...
notifyListeners();
}
Its better to use a function outside the constructor and use that, the constructor will create once when you provide the provider,
Related
Imagine this workflow of 10 activities in a loop:
public class LoopWorkflowImpl implements LoopWorkflow{
private final Api api = Workflow.newActivityStub(Api.class, ...)
#override
public int start(){
int sum = 0;
for(int i=0; i<10; i++){
sum += api.getCount();
}
return sum;
}
}
How can I change api.getCount() to api.getCountV2() for existing workflows?
E.g. if there is workflow already completed 5 activities with api.getCount(), how can let let it use api.getCountV2() for the rest 5 activities?
Correct Way to apply new behavior for old and new workflow
This is what you should do -- using the versioning API with changeId for each iteration:
public class LoopWorkflowImpl implements LoopWorkflow{
private final Api api = Workflow.newActivityStub(Api.class, ...)
#override
public int start(){
int sum = 0;
for(int i=0; i<10; i++){
int version = Workflow.getVersion("useV2API"+i, Workflow.DEFAULT_VERSION, 1)
if( version == 1){
sum += api.getCountV2();
}else{
sum += api.getCount();
}
}
return sum;
}
}
Below will only apply for new workflows
Many people will do this instead and it won't work for the existing workflow
public class LoopWorkflowImpl implements LoopWorkflow{
private final Api api = Workflow.newActivityStub(Api.class, ...)
#override
public int start(){
int sum = 0;
for(int i=0; i<10; i++){
int version = Workflow.getVersion("useV2API", Workflow.DEFAULT_VERSION, 1)
if( version == 1){
sum += api.getCountV2();
}else{
sum += api.getCount();
}
}
return sum;
}
}
Why
This is because of an important contract of Workflow.getVersion() API --
The return value from the API for the same changeId is immutable once returned. This is guaranteed with or without the version is being written into history using MarkerRecord event.
So in the 2nd solution , on the first iteration, Workflow.getVersion() will returns Workflow.DEFAULT_VERSION(-1) as there is no version marker during replay. So in the rest iteration, it will always return Workflow.DEFAULT_VERSION.
The best way to fix is to include the iteration Id into the changeId. Using the different changeId will allow the versioning to pick different version for different iteration.
If you are worried about this will create too many version marker events in the history, you can combine this solution with the global versioning pattern to only do this for old workflows:
public class LoopWorkflowImpl implements LoopWorkflow{
private final Api api = Workflow.newActivityStub(Api.class, ...)
private GlovalVersionProvider globalVersionProvider = GlobalVersionProvider.get();
#override
public int start(){
if (globalVersionProvider.isAfterVersionOfUsingGlobalVersion()) {
GlobalVersionProvider.upsertGlobalVersionSearchAttribute();
}
int sum = 0;
for(int i=0; i<10; i++){
if (globalVersionProvider.isAfterVersionOfUsingV2Api()) {
sum += api.getCountV2();
}else{
int version = Workflow.getVersion("useV2API"+i, Workflow.DEFAULT_VERSION, 1)
if( version == 1){
sum += api.getCountV2();
}else{
sum += api.getCount();
}
}
}
return sum;
}
}
So the the versioning marker with iteration index is only applying for existing old workflow executions.
[1][I write a simple program in dart to print multiplication table but the output was not I Except][1]
void main{
int num=10;
for(var i=1;i<=10;++i){
print('$num*$i=$num');
}
}
this was my code
Finally I found the answer
var num = 10;
for (var i = 1; i < 10; i++) {
print("$num * $i = ${num * i}");
}
any other ways to print multiplication table in dart using for loop
You forget to add the parenthesis in the main function which acted like a function declaration.
And you also missed to multiply the result of the multiplication by i.
The correct code is :
void main(){
int num=10;
for(var i=1;i<=10;++i){
print('$num*$i=${num*i}');
}
}
instead of this:
void main{
int num=10;
for(var i=1;i<=10;++i){
print('$num*$i=$num');
}
}
void main()
{
int num =20;
for(int i=1;i<=10;i++)
{
print("num* $i = ${num*2}");
}
}
I've faced with the problem and been trying to solve it for almost an hour. I'm sharing this just in case anyone may face with the same problem. To explain the question and answer more clearly here is an example:
1) Let's say you create some button objects dynamically and add pile them up in a List:
private void CreateButtons(int length)
{
for (int i = 0; i < length; i++)
{
var newButton = Instantiate(buttonPrefab);
buttonList.Add(newButton);
}
}
2) Then you want to assign same function to different buttons but with different parameters:
Here is the assigned method:
private void Test(int a)
{
print(a);
}
And here is the assigning loop:
private void AssignClickEvents()
{
for (int i = 0; i < buttonList.Count; i++)
{
buttonList[i].GetComponent<Button>().onClick.AddListener(() => { Test(i); });
}
}
The problem with the above code is that when a button is clicked it won't give you 0,1,2... etc. All buttons will give you the same value which is last assigned value of loop parameter 'i'. Check answer for solution:
I don't know the exact reason behind this but to get things work you need to use a local variable for function parameter. Here is the code:
private void AssignClickEvents()
{
for (int i = 0; i < buttonList.Count; i++)
{
int a = i;
buttonList[i].GetComponent<Button>().onClick.AddListener(() => { Test(a); });
}
}
I hope it helps!
I have a class which I used to overlay rectangles on maps. But I am not able to figure out how to remove the previous overlay's to draw new rectangles if a new set of results are provided to my displayOnMap method.
To provide more insight on the draw method. It takes in PlotSetOutput as an argument which contains centers and each center contains a set of lat/long co-ordinates. Hence the logic for looping over it and creating lat/long bounds and assigning it to rectangle objects.
public class displayOnMap extends Composite {
private final VerticalPanel pWidget;
private MapWidget mapWidget;
private static Rectangle rectangle;
private RectangleOptions rectOpts;
private static final LatLng USCENTER = LatLng.newInstance(33.68,-116.17);
public displayOnMap(PlotSetOutput result) {
pWidget = new VerticalPanel();
initWidget(pWidget);
draw(result);
}
private void draw(PlotSetOutput result) {
MapOptions mapOpts = MapOptions.newInstance();
mapOpts.setZoom(4);
mapOpts.setCenter(USCENTER);
mapOpts.setMapTypeId(MapTypeId.TERRAIN);
mapWidget = new MapWidget(mapOpts);
pWidget.add(mapWidget);
mapWidget.setSize("800px", "800px");
ArrayList<Centers> listOfCenters = new ArrayList<Centers>();
List<ResultClusterPlots> finalCluster = result.getFinalcluster();
int totalNumberOfClusters = result.getTotalNumberOfClusters();
for (int i = 0; i < totalNumberOfClusters; i++) {
listOfCenters.add(i, new Centers());
}
for (int j = 0; j < finalCluster.size(); j++) {
Centers p = listOfCenters.get(finalCluster.get(j).getClusterID()-1);
LatLng ne = LatLng.newInstance(finalCluster.get(j).getLatitude()
.get(0), finalCluster.get(j).getLongitude().get(0));
LatLng sw = LatLng.newInstance(finalCluster.get(j).getLatitude()
.get(1), finalCluster.get(j).getLongitude().get(1));
p.setLatLongArr(LatLngBounds.newInstance(ne,sw));
}
for (int k = 0; k < listOfCenters.size(); k++) {
ArrayList<LatLngBounds> ltlgBound = listOfCenters.get(k).getLatLongArr();
String color = getRandomColor();
for (int l = 0; l < ltlgBound.size(); l++) {
rectOpts = RectangleOptions.newInstance();
rectOpts.setStrokeColor("#FF0000");
rectOpts.setStrokeOpacity(0.3);
rectOpts.setStrokeWeight(2);
rectOpts.setFillColor(color);
rectOpts.setFillOpacity(0.35);
rectOpts.setMap(mapWidget);
rectOpts.setBounds(ltlgBound.get(l));
rectangle = Rectangle.newInstance(rectOpts);
rectangle.setMap(mapWidget);
}
}
}
}
Output when the method (displayOnMap) is invoked for the first time. Everything works fine.
Output when the displayOnMap method is called with a second query.
I tried to do rectangle.setMap(null); pWidget.removeFromParent(); but I kept getting the same result.
I have had the same problem, the only way I could hide / delete / show the overlays was through the OverlayCompleteMapEvent.
As I understand it isn't possible to get a hook to an overlay before it is completed, once it is completed the only way to get a hook on it is handling "OverlayCompleteMapEvent" event. I used a list to store the Overlays and then I could hide/show/delete them.
I use flex table to show the data fetched from db. When table contains a large amount of columns it takes much time to render the flextable(I've tested it on table with 80 columns and 38 rows) and while it is not completely rendered I can not do anything with a page. So i use Schedule.get().scheduleIncremental(ReapitingCommand command) as follows:
final int WORK_CHUNK = 2;
Scheduler.get().scheduleIncremental(new RepeatingCommand() {
int rowCounter = 0;
#Override
public boolean execute() {
for (int i = rowCounter; i < rowCount; i++, rowCounter++) {
for (int j = 0; j < columnCount; j++) {
table.setText(i, j, data.get(i)[j]);
}
if (rowCounter % WORK_CHUNK == 0)
return true;
}
return false;
}
});
But if i have 9 rows and 3 columns in data object it only render 2 rows.
How I can improve its performance, because as I said earlier if have 38 rows and 80 columns it takes too much time to render all the data without scheduleIncremental. Even browser popups the window that script may have stoped responing.
Why don't use a CellTable instead of a FlexTable to render your data?
CellTable is supposed to be much more efficient in rendering large amounts of data compared to FlexTable.
For above code I would have done it this way. Get rid of the first for loop because execute() is recursive.
Scheduler.get().scheduleIncremental(new RepeatingCommand() {
int rowCounter = 0;
int rowCount = 10;
#Override
public boolean execute() {
// do some work
for (int j = 0; j < columnCount; j++) {
table.setText(i, j, data.get(i)[j]);
}
rowCounter++;
if (rowCounter >= rowCount)
return false;
return true;
}
});