I am using flutter webview plugin.
getCookies() will return a Future<Map<String, String>>.
the containsKey function is false even "id" exist in the Map.
I have no problem if the Map does not come from Future.
How can I access the value from Map?
flutterWebviewPlugin.getCookies().then((Map<String, String> _) {
if (_.containsKey("id")) {
print(${_["id"]});
}
});
print map by
flutterWebviewPlugin.getCookies().then((Map<String, String> _) {
print(_);
}
output of map values
{"locale: en, tcurrency: 6, id: 10702776, pbe: "}
I fix the cookie by this now
_flutterWebviewPlugin.getCookies().then((Map<String, String> cookies) {
Map<String, String> trimCookies = {};
for (String key in cookies.keys) {
trimCookies[key.replaceAll("\"", "").trim()] = cookies[key].replaceAll("\"", "");
}
}
Related
I have a list of paths like the following:
[ "animal/cat/persian", "animal/cat/british_shorthait",
"animal/dog/pug", "animal/dog/pitbull", "vehicle/car/mercedes",
"vehicle/car/bmw"]
and I need to convert it into a nested structure (Map)
{
'animal': {
'cat': {
'Persian': {},
'British_Shorthair': {}
}
'dog': {
'Pug': {},
'Pitbull': {}
}
}
'vehicle': {
'car': {
'Mercedes': {},
'BMW': {}
}
}
The paths are of varying length and can be infinitely deep.
Any ideas on how to do this in a performant manner?
This is akin to a reverse of this question
Initialize an empty Map for the results.
For each path in your list, split it into a list of keys. Use the Map from step 1 as the initial Map for each path.
For each key, retrieve the nested Map for that key in the current Map, creating it if necessary. Make the retrieved Map the current one.
import 'dart:convert';
void main() {
var mapPaths = [
"animal/cat/persian",
"animal/cat/british_shorthair",
"animal/dog/pug",
"animal/dog/pitbull",
"vehicle/car/mercedes",
"vehicle/car/bmw",
];
var mapRoot = <String, dynamic>{};
for (var path in mapPaths) {
var currentMap = mapRoot;
for (var key in path.split('/')) {
currentMap = currentMap[key] ??= <String, dynamic>{};
}
}
// Pretty-print `mapRoot`.
print(JsonEncoder.withIndent(' ').convert(mapRoot));
}
I'm trying to change a layout from CircleLayout to StaticLayout, keeping the positions of the Vertex, to do this im using the following code:
StaticLayout<VertexType, EdgeType> sLayout = new StaticLayout<VertexType, EdgeType>(graph,
new Transformer<VertexType, Point2D>() {
public Point2D transform(VertexType vertex) {
vertex.setX(layout.getX(vertex));
vertex.setY(layout.getY(vertex));
System.out.println(vertex.toString());
System.out.println(vertex.getX());
System.out.println(vertex.getY());
Point2D p = new Point2D.Double(vertex.getX(), vertex.getY());
return p;
}
}, dimension);
currentVV.setGraphLayout(sLayout);
Where currentVV is a VisualizationViewer and layout is a CircleLayout. setX(double) and setY(double) are methods from my custon Vertex, by default the vertex is initializated with x = 0.0 an y = 0.0.
In this stage I used teh println to check if all vertex get their positions correctly and it is working.
The next step is to save the graph using the GraphmlWritter:
GraphMLWriter<VertexType, EdgeType> graphWriter = new GraphMLWriter<VertexType, EdgeType>();
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
graphWriter.addEdgeData("label", null, "0", new Transformer<EdgeType, String>() {
#Override
public String transform(EdgeType v) {
return v.toString();
}
});
graphWriter.addVertexData("x", null, "0", new Transformer<VertexType, String>() {
public String transform(VertexType v) {
return Double.toString(v.getX());
}
});
graphWriter.addVertexData("y", null, "0", new Transformer<VertexType, String>() {
public String transform(VertexType v) {
return Double.toString(v.getY());
}
});
graphWriter.save(graph, out);
The problems is that while most of the vertexes are being saved sucessfully, some of the vertexes are being saved with the default values to X and Y (0.0), and I have no idea why. If I try to save the graph from directly from the CircleLayout getting the X and Y values from the layout with:
GraphMLWriter<VertexType, EdgeType> graphWriter = new GraphMLWriter<VertexType, EdgeType>();
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
graphWriter.addEdgeData("label", null, "0", new Transformer<EdgeType, String>() {
#Override
public String transform(EdgeType v) {
return v.toString();
}
});
graphWriter.addVertexData("x", null, "0", new Transformer<VertexType, String>() {
public String transform(VertexType v) {
return Double.toString(layout.getX(v));
}
});
graphWriter.addVertexData("y", null, "0", new Transformer<VertexType, String>() {
public String transform(VertexType v) {
return Double.toString(layout.getY(v));
}
});
While this solution helps I would prefer to save the X and Y values on the vertex as it will be used for future implementations.
Anyone knows where I'm missing the position info?
Thanks.
I'm not immediately sure where the bug in your code is.
First question: why are you trying to convert a CircleLayout to a StaticLayout? What does that buy you?
Assuming that this is actually what you need to do, you don't need to serialize it at all; you can initialize any AbstractLayout subclass with the positions of any other Layout instance, because a Layout is (among other things a Function<V, Point2D>, which means you can pass it to an AbstractLayout instance as an "initializer". Thus, for example:
CircleLayout<V, E> circleLayout = ...
...
StaticLayout<V, E> staticLayout = new StaticLayout(graph, circleLayout);
I have defined a static var as Map for all instances of my element. If it contains a specific key, it should use the value. If the key is not contains the instance should get the data with a request and save it in the static map, so other instances could use it.
static var data = new Map();
func() {
if (Elem.data.containsKey(['key']) {
list = Elem.data['key'];
}
else {
Helper.getData().then((requestedData) {
list = requestedData;
Elem.data.addAll({ 'key' : requestedData });
}
}
The Problem is that all my instances go into the else, since the key is not contained in the Map at the moment the other instances are at the if. So i need them to wait, until the Data is in the Map.
static var data = new Map();
static Completer _dataCompleter;
Future<bool> func() {
if(_dataCompleter == null) {
_dataCompleter = new Completer();
Helper.getData().then((requestedData) {
list = requestedData;
Elem.data.addAll({ 'key' : requestedData });
_dataCompleter.complete(true);
})
}
if(_dataCompleter.isCompleted) {
return new Future.value(true);
}
return _dataCompleter.future;
}
and call it like
func().then((success) => /* continue here when `key` in `data` has a value.
In response to Günter Zöchbauer. I generally avoid using Completers directly:
static var data = new Map();
static Future _pendingFuture;
Future func() {
if (_pendingFuture == null) {
_pendingFuture = Helper.getData().then((requestedData) {
list = requestedData;
Elem.data.addAll({ 'key' : requestedData });
});
}
return _pendingFuture;
}
I would like to be able to back a dynamic property with a Map using a lookup in noSuchMethod(). However the latest changes makes the incoming property reference name unavailable. I can understand the minification scenario requiring us to use Symbols rather than Strings for names, but this makes implementing serializable dynamic properties difficult. Anyone have good ideas on how to approach this problem?
I can't use String names since the String names are not fixed between calls to the minifier. (This would completely break serialization)
You can access the original name with MirrorSystem.getName(symbol)
So a dynamic class could look like :
import 'dart:mirrors';
class A {
final _properties = new Map<String, Object>();
noSuchMethod(Invocation invocation) {
if (invocation.isAccessor) {
final realName = MirrorSystem.getName(invocation.memberName);
if (invocation.isSetter) {
// for setter realname looks like "prop=" so we remove the "="
final name = realName.substring(0, realName.length - 1);
_properties[name] = invocation.positionalArguments.first;
return;
} else {
return _properties[realName];
}
}
return super.noSuchMethod(invocation);
}
}
main() {
final a = new A();
a.i = 151;
print(a.i); // print 151
a.someMethod(); // throws
}
You could do something like this:
import 'dart:json' as json;
main() {
var t = new Thingy();
print(t.bob());
print(t.jim());
print(json.stringify(t));
}
class Thingy {
Thingy() {
_map[const Symbol('bob')] = "blah";
_map[const Symbol('jim')] = "oi";
}
final Map<Symbol, String> _map = new Map<Symbol, String>();
noSuchMethod(Invocation invocation) {
return _map[invocation.memberName];
}
toJson() => {
'bob': _map[const Symbol('bob')],
'jim': _map[const Symbol('jim')]};
}
Update - dynamic example:
import 'dart:json' as json;
main() {
var t = new Thingy();
t.add('bob', 'blah');
t.add('jim', 42);
print(t.bob());
print(t.jim());
print(json.stringify(t));
}
class Thingy {
final Map<Symbol, String> _keys = new Map<Symbol, String>();
final Map<Symbol, dynamic> _values = new Map<Symbol, dynamic>();
add(String key, dynamic value) {
_keys[new Symbol(key)] = key;
_values[new Symbol(key)] = value;
}
noSuchMethod(Invocation invocation) {
return _values[invocation.memberName];
}
toJson() {
var map = new Map<String, dynamic>();
_keys.forEach((symbol, name) => map[name] = _values[symbol]);
return map;
}
}
If you only need "dynamic properties", it should be enough to use Symbols as keys in the Map. If you also want to serialize that map, then you need to keep track of the original String names and use those for serialization. When deserializing, you'd have to create new Symbols from those Strings.
Note that all these scenarios (and basically everything that involves new Symbol) require a compiler to create a mapping of original names to the minified ones and put this mapping into the program, which of course makes it bigger.
Thanks for the solution of #Alexandre Ardhuin, I made some modification to make it runnable.
import 'dart:mirrors';
class object {
final _properties = new Map<String, Object>();
object();
object.from(Map<String, Object> initial) {
initial.entries.forEach((element) => _properties[element.key] = element.value);
}
noSuchMethod(Invocation invocation) {
if (invocation.isAccessor) {
final realName = MirrorSystem.getName(invocation.memberName);
if (invocation.isSetter) {
// for setter realname looks like "prop=" so we remove the "="
final name = realName.substring(0, realName.length - 1);
_properties[name] = invocation.positionalArguments.first;
return;
} else {
return _properties[realName];
}
}
return super.noSuchMethod(invocation);
}
#override
String toString() {
return _properties.toString();
}
}
main() {
// we can't use var or object type here, because analysis will consider
// https://dart.dev/tools/diagnostic-messages#undefined_setter
// The setter 'i' isn't defined for the type 'object'
// So dynamic is required here!
dynamic a = object.from({'a': 123, 'b': 234});
a.i = 151;
print(a); // print {a: 123, b: 234, i: 151}
try {
a.someMethod(); // throws NoSuchMethodError
} catch (e) {
print(e);
}
}
How do I get the parameter / value pairs of an URL / URI using Dart? Unfortunately currently there is no built-in functionality for this problem neither in the Uri library or the Location interface.
You can use Uri.splitQueryString to split the query into a map.
There is now a queryParameters member of Uri that returns a Map
Uri u = Uri.parse("http://app.org/main?foo=bar&baz=bat");
Map<String,String> qp = u.queryParameters;
print(qp);
// {foo: bar, baz: bat}
// url=http://127.0.0.1:3030/path/Sandbox.html?paramA=1&parmB=2#myhash
void main() {
String querystring = window.location.search.replaceFirst("?", "");
List<String> list = querystring.split("&").forEach((e) => e.split("="));
print(list); // [[paramA, 1], [parmB, 2]]
}
Map<String, String> getUriParams(String uriSearch) {
if (uriSearch != '') {
final List<String> paramValuePairs = uriSearch.substring(1).split('&');
var paramMapping = new HashMap<String, String>();
paramValuePairs.forEach((e) {
if (e.contains('=')) {
final paramValue = e.split('=');
paramMapping[paramValue[0]] = paramValue[1];
} else {
paramMapping[e] = '';
}
});
return paramMapping;
}
}
// Uri: http://localhost:8080/incubator/main.html?param=value¶m1¶m2=value2¶m3
final uriSearch = window.location.search;
final paramMapping = getUriParams(uriSearch);