Should you call clear() on a list inside setState or set the list to an empty array? - flutter

I'm wondering how I should clear a list that the UI depends on. Here are two options:
//first implementation
setState(() {
list.clear();
});
//second implementation
setState(() {
list = [];
});
Which one is better? Thanks

Generally speaking I would say look at the clear Method implementation to find out what the method does under the hood. You probably will find arguments why you should use the method.
An easy answer is to generally use provided methods because chanches are that the method is not only for convenience and nice naming but also takes care of some things u are not aware of right now.

Either one is fine but you should know .clear() "throws an UnsupportedError, and retains all objects, if this is a fixed-length list." Source

Related

want to make a method that toggle my transaction with expense to income and vice versa in flutter

I have created a method to toggle transaction type, like converting expense to income and income to expense...
and I created following method
void swapTransaction(TransactionModel transaction)
{
transaction.isExpense=!transaction.isExpense;
update();
}
it worked fine but than I was forced to apply following method,
void swapTransaction(TransactionModel transaction)
{
int index=_transactions.indexOf(transaction);
_transactions[index].isExpense=!_transactions[index].isExpense;
update();
}
here I want to know what is the better method to apply... is there any big difference?
I'm not sure if such questions are suitable for this site, as it can be "opinion based" but here's my take:
I think the second method is better since you are updating the actual _transactions list, but in the first example, you are just updating what's getting passed into the function - the TransactionModel, so you're not actually changing the list of _transactions.
According to me, second one is better.
In first one you are passing one copy of object to update, which is just used within that function. While in second one you are actually updating your actual list of transaction, which you used to display.

Reusing BodyHandler instance

I'm trying to create something like
router.route("foo").handler(BodyHandler.create().setBodyLimit(1024*1024))
router.route("bar").handler(BodyHandler.create().setBodyLimit(1024*1024))
router.route("baz").handler(BodyHandler.create().setBodyLimit(1024*1024))
Would it be ok to call BodyHandler.create().setBodyLimit(1024*1024) only once in the app, and reuse it all over the place I need it?
From what I can tell, you should be able to share BodyHandler between multiple routes. In fact, it is usually shared by setting it on all routes, as was correctly pointed out in another answer.
You can take a look at the code and see that it doesn't mutate anything internaly, so should be safe.
var defaultBodyHandler = BodyHandler.create().setBodyLimit(1000L);
router.route("foo").handler(defaultBodyHandler).handler((ctx) -> {});
router.route("bar").handler(defaultBodyHandler).handler((ctx) -> {});
Yes, you can re-use it. But it might make sense, according to what is provided in the question, to define a global BodyHandler:
router.route().handler(BodyHandler.create().setBodyLimit(1024*1024))
router.route("foo")...
router.route("bar")...
router.route("baz")...

How to copy a Map in dart without getting Reference of the old one

I have a map that i get from my service and i want to copy it into 2 new Maps without being referenced and every time i change a value into one, value change to other too.
This is the Initial Map from my service config.UserGroups and i copy it like this
SavedSettings.UserGroups = new Map.from(config.UserGroups);
UnSavedSettings.UserGroups = new Map.from(config.UserGroups);
This Map is dynamic but it has String,object
Do we have an easy way to bypass reference;
What you are asking for is called deep copying and is something you need to implement yourself for your data structures since List and Map just contains references to objects. So when you are making a copy of a List or Map, you are copying the references and not the objects inside the collection.
So the correct solution would be to make some logic which allows you to make copies of UserGroup objects and put these into your new list.
But.... if you are not scared of hacky solutions....
Section with hacky solution
If you really want to have some way to get deep copy from the Dart language (and don't care if the solution is kinda hacky) it is in theory possible by make use of the idea that we can send objects to isolates which are deep copied if possible.
So we can create an ReceivePort and send our object to our self. An example of this can be seen in this example:
class MyObject {
int value;
MyObject(this.value);
#override
String toString() => 'MyObject($value)';
}
Future<void> main() async {
final list1 = [MyObject(5)];
final list2 = await hackyDeepCopy(list1);
list2[0].value = 10;
print(list1); // [MyObject(5)]
print(list2); // [MyObject(10)]
}
Future<T> hackyDeepCopy<T>(T object) async =>
await (ReceivePort()..sendPort.send(object)).first as T;
This "solution"/hack comes with some limitations when it comes to data we can copy:
The content of message can be:
Null
bool
int
double
String
List or Map (whose elements are any of these)
TransferableTypedData
SendPort
Capability
In the special circumstances when two isolates share the same code and
are running in the same process (e.g. isolates created via
Isolate.spawn), it is also possible to send object instances (which
would be copied in the process). This is currently only supported by
the Dart Native platform.
https://api.dart.dev/stable/2.14.4/dart-isolate/SendPort/send.html
It is the "In the special circumstances when two isolates share the same code and are running in the same process" part we makes use of in hackyDeepCopy which allows us to also deep copy custom made objects.
Another limitation is that hackyDeepCopy needs to be async which is kinda annoying if your code is not already async.
And lastly, this only really works on native platforms (so no Dart-running-as JavaScript stuff).

How to make copy of array's elements in the dart

Getting wired issue like main array has been changed if changed value of another array. I think issue is about copying same address, not sure but just thinking of it. I have tried from last 3 hours but unable to get rid from it.
Look at below illustration to get better idea.
List<page> _pageList;
List<page> _orderList = [];
_pageList = _apiResponse.result as List<page>;
_orderList.add(_pageList[0].element);
_orderList[0].title = "XYZ"
//--> Here if I change the `_orderList[0].title` then it also change the `title` inside "_pageList"
How can we prevent the changes in main array?
I got same issue in my one of the project. What I have done is, use json to encode and decode object that help you to make copy of the object so that will not be affected to the main List.
After 3rd line of your code, make changes like below
Elements copyObject = Elements.fromJson(_pageList[0].element.toJson());
// First of all you have to convert your object to the Map and and map to original object like above
_orderList.add(copyObject);
Hope that will help you.
You can use a getter function to create a copy of your list and use that instead of
altering your actual list.
example:
List<Page> get orderList{
return [..._orderList];
}
Lists in Dart store references for complex types, so this is intended behaviour.
From your code:
_orderList.add(_pageList[0].element);
_orderList[0] and _pageList[0].element point to the same reference (if they are non-primitive).
There is no general copy() or clone() method in dart, as far as i know. So you need to copy the object yourself, if you want a separate instance. (see this question)

How to expect on method calls that has inline new instance creations in easymock

We have following code structure in our code
namedParamJdbcTemplate.query(buildMyQuery(request),new MapSqlParameterSource(),myresultSetExtractor);
and
namedParamJdbcTemplate.query(buildMyQuery(request),new BeanPropertySqlParameterSource(mybean),myresultSetExtractor);
How can I expect these method calls without using isA matcher?
Assume that I am passing mybean and myresultSetExtractor in request for the methods in which above code lies.
you can do it this way
Easymock.expect(namedParamJdbcTemplateMock.query(EasyMock.anyObject(String.class),EasyMock.anyObject(Map.class),EasyMock.anyObject(ResultSetExtractor.class))).andReturn(...);
likewise you can do mocking for other Methods as well.
hope this helps!
good luck!
If you can't use PowerMock to tell the constructors to return mock instances, then you'll have to use some form of Matcher.
isA is a good one.
As is anyObject which is suggested in another answer.
If I were you though, I'd be using Captures. A capture is an object that holds the value you provided to a method so that you can later perform assertions on the captured values and check they have the state you wanted. So you could write something like this:
Capture<MapSqlParameterSource> captureMyInput = new Capture<MapSqlParameterSource>();
//I'm not entirely sure of the types you're using, but the important one is the capture method
Easymock.expect(namedParamJdbcTemplateMock.query(
EasyMock.anyObject(Query.class), EasyMock.capture(captureMyInput), EasyMock.eq(myresultSetExtractor.class))).andReturn(...);
MapSqlParameterSource caughtValue = captureMyInput.getValue();
//Then perform your assertions on the state of your caught value.
There are lots of examples floating around for how captures work, but this blog post is a decent example.