Flutter, can i pass a Map for the named parameters - android

if i have levels of named parameters that needs to be passed down, i don't want to typeout the named parameter for ever method eg,
BaseText(text,options)
LargerText(text,options)
MenuText(text,options)
eventually i need to pass this to the Text Widget with the different defaults,
but to write out all of the parameters, and pass each on down seems like alot of work,
how can i get around this.
in JS i would just do
LargerText(text,options){
options = {...defaultOptions,...options}
return BaseText(text,options)
}

If Dart supported spreading map into named arguments, this would either reduce type safety, or introduce overhead checks.
Use objects to get around this. This is exactly what objects are for. With each call a compiler checks if the class is what the method expects and so all the fields present. You would not have this with maps.

Related

What is typed array in kotlin

I am not able to clearly understand what is typed array in kotlin. I have seen the fucntion toTypedArray in kotlin. but did not see any proper definition of it like what exactly it does. Can anyone please explain with an example.
Thanks
Arrays are generic data structures because they can contain different types of elements. You can have Array<Int> or Array<String> for instance.
There is no separate concept of "typed" array. The reason for the name of toTypedArray is (I guess) to distiguish it from toArray() which returns an Array<Any?> (without useful type information about its elements, because everything is a Any? in Kotlin).
The reason why those 2 exist is because arrays on the JVM cannot be created without knowing the element type. This means that, in general, you cannot create an arbitrary array generically because generics are erased at runtime so you wouldn't actually know the correct element type at that time. This is why the simple toArray method either returns Array<Any?> or takes an extra array argument. The extra argument allows to either avoid creating the destination array, or at least provides sufficient type information at runtime to create an array of the same type.
In Kotlin, we can go one step further and actually use reified types to use information that we have at compile time to generate more specific code, such as code that create an array of a specific type (not generically, but directly with the correct element type based on the call site information). This is what toTypedArray does by reifying its type parameter.

Is setting fields line after line from a Firestore document read an anti-pattern?

I have a document on Firestore, from which I read its fields in a fragment. Since it has many fields, I set variables in the Activity that hosts this fragment so that I can pass the data between other fragments. In order to achieve that, I realize that I have to write similar lines of codes over and over again, which got me to thinking if there is a better way.
Two possible solutions that come to my mind:
Structure all these fields in JSON format -> something that wouldn't be suitable in Firestore's document system imo
Put all these fields into a serializable data class which I keep in the activity then pass it around the bundles of fragments -> Seemed to complicated and I would still have to write it.get(foo) as bar for each of the field's of this class' constructor.
Given all these, what is the best approach? Thanks in advance.
You have a several options on how to approach this. There is none that's necessarily better than another. Ultimately, you will pick the one that best suits your needs and preferences.
You can do what you're doing now.
You can go a step further an actually check the types of the values instead of just blindly casting them (which would cause a crash at runtime if they didn't match).
You can provide a Class object to get(String, Class<T>) that can automatically map the fields to properties in a new object of type T, as long as the types also match.
You can call a variety of type-specific versions of get, such as getString()
Ultimately you will have to decide if you are going to trust what you get in the snapshot and allow errors to happen, or trust nothing and check everything. It's up to you.

How to pass a dynamic amount of arguments to strings.xml?

Passing one or two arguments to a string in strings.xml it's possible doing this:
<string name="test">%1$s from %2$s.</string>
context.getString(R.string.test, name, name2);
result:
Pedro from Pablo.
The problem is that now I need to pass a dynamic amount of arguments, not knowing how much in each case, my idea is to get a result similar to this:
Pedro from Pablo, Paco, Peco, Puco.
It is possible to do it with a XML trick? or the only way is to do it manually with Java code?
Don't think this is possible with Android resources, because the number of arguments to substitute is always fixed, they have a fixed position and there is nothing which could represent a repeating pattern. Only Java methods support an arbitrary number of arguments with String..., where the ... means varargs.
String resources could only be used as far as defining the basic sentence and the repeating pattern, but gluing that together requires custom code - else it won't ever be a truly dynamic substitution.
Passing Information to a Method or a Constructor explains it.
You have to define it through Java only. if you know the no of dynamic content then you can define it in xml. according to your need. you have generate the second argument in loop separated by comma an then pass it to xml.

Where to put helper methods?

I have a method that darkens a given hex color and percent. Currently, the only place I use this method is within one of my Activity classes (I may or may not end up using it in other classes later on).
public static int darkenColor(int color, int percent) { ... }
However, where should I put this method? Should I create a new class called Helpers that contains all of these methods that I may use only once throughout the entire app?
This is just a matter of choice. You can have Set of utility classes and have these helper methods to be in those classes. But, This method is for not used in one of your activity, and If you do not see that it will get reused in the near future in some other point, Put it as a private method inside your Activity. I say this because you do not want to over complicate the code and also By this way another developer can easily follow the flow of execution.
But after sometimes if you feel, that this code is getting reused, put that into a logically meaningful Utility class. When the code base is huge, you do not have any choice to follow a solid standardization of there to put your code, That is why there are things like Layered architectures etc.

Android Patterns: A Spinner where every item launches a different Activity

I'm trying to build a complex form where almost all of the elements are optional. It starts with just a single field and an "add element" button. When you click add, the form shows a Spinner of the types of elements you can add to the form (location, photo, detailed note, timestamp other than "now", etc). When you select an item, it will launch an Activity, and each item has a different associated Activity.
In addition, each choice will have several bits of data, which it would be nice to store "with" the Activity somehow:
An icon and the displayed name in the Spinner
A key for storing the data in the db (as well as passing to a webservice)
A layout for how to display the result on the original form (i.e. a thumbnail for the photo, the lat/lon for the location, etc)
I was considering a set of classes that all extend an abstract FormElement class, and would have static elements for each of the above extra pieces of data. (An additional bump for this solution is how much of a pain Resources are in a static context.)
How can I make this as clean and maintainable as possible? I'd really not enjoy editing five different files to add a new type of element to this form. (Mostly because I can guarantee I'll miss one and spend hours chasing down unbugs.)
A few tips...
Unit tests will prevent "unbugs" :)
When each Activity has obtained the information it needs from the user, call Activity#setResult() with an Intent that contains your per-type data. Intent supports all the Bundle methods, so you can set different types of data as needed.
To support #2, make sure you're using Activity#startActivityForResult(Intent,int) to launch it, and listen for the result in Activity#onActivityResult(int,Intent)
I would probably maintain the list of available "element" types for use with the SpinnerAdapter (e.g., ArrayList<Class<? extends AbstractFormElement>>, and invoke static methods like .getDisplayName(), .getActivityClass(), etc, in the Adapter's getView() method, in order to determine what to display and what Activity to launch.
In this way, your list would actually contain things like { MyPhotoElement.class, MyTextElement.class, MyDateElement.class, ...}).
As each element is added to the form, add it to an ArrayList<AbstractFormElement>, which will be used to back another Adapter for a ListView. That adapter will dispatch the inflation of a custom view layout, as well as the creation of a ViewHolder, based on what type of object it is -- that will require that each distinct AbstractFormElement will have its own "view type", according to the Adapter. See BaseAdapter#getItemViewType(int) and related getViewTypeCount().
It's worth noting that these will need distinct view types only if one cannot be converted to the other... For example, if you have two "Elements" that only need to display a string of text in the list, those can both share a "text-only" view type. Likewise, two elements that only display a photo, or can easily convert one to the other (e.g., an icon with a caption, vs a photo thumbnail with no caption), can share a single "image-plus-caption" view type.
With the above in mind, you actually would end up having to modify different files to add a new type (well, I guess technically you could have them all in one file, as inner classes, but there's really no good argument for doing that), but if you've done your interface API correctly, and follow good OO practices, and implement good unit tests, you'll considerably reduce the amount of effort required to find bugs -- simply because most of the things involved in adding a new type would actually force a compiler error if you do it incorrectly. Add to that the fact that a proper unit test suite will be able to programmatically add all possible types, and ensure that everything displays properly, and you should have a pretty streamlined process for easy extensibility :)
It sounds like a lot of work, and it might seem tedious and verbose at first... But the end result is actually much more maintainable, especially if your list of element types is going to be fairly extensive.

Categories

Resources