How to use Parceler with ArrayList<Map<String, String>>? - arraylist

I'm trying to use Parceler to transfer variable of ArrayList>, but it always give error when running, just link intent.putParcelableArrayListExtra("votedetail", arrlist);. Searched and found no example, how to use it? Thank you in advance.

Please take a look at the method's signature on Android Developer docs:
Intent putParcelableArrayListExtra (String name, ArrayList<? extends Parcelable> value)
The objects in the ArrayList have to be Parcelables.
As far as I know, Android SDK implementations of Map<K,V> (HashMap, SortedMap, etc) do not implement Parcelable. You will have to write your own implementation which will also be Parcelable.

B0Andrew, Thank you for your help. I found the answer at last. Using putParcelableArrayList to do it. First wrap the
"Arraylist<Map<String, String>>"
to become Arraylist(new one Arraylist, then add the variable), then I can use putParcelableArrayList to transfer the data.

Parceler is a library for serializing Parcelable objects. There is no need to use putParcelableArrayListExtra(), just use putParcelable():
List<Map<String, String>> value = new ArrayList<>();
// Fill out List
intent.putParcelable("votedetail", Parcels.wrap(value));
And you may deserialize in the onCreate of the receiving activity:
List<Map<String, String>> value = intent.getParcelableExtra("votedetail");
You can find examples on how to use it directly on the website: http://parceler.org/

Related

Optaplanner: prevent custom List from beeing cloned by FieldAccessingSolutionCloner

I have a #PlanningSolution class, that has one field with a custom List implementation as type.
When solving I run into the following issue (as described in the optaplanner documentation):
java.lang.IllegalStateException: The cloneCollectionClass (class java.util.ArrayList) created for originalCollectionClass (class Solution$1) is not assignable to the field's type (class CustomListImpl).
Maybe consider replacing the default SolutionCloner.
As this field has no impact on planning, can I prevent FieldAccessingSolutionCloner from trying to clone that particular field e.g. by adding some annotation? I dont want to provide a complete custom SolutionCloner.
When inspecting the sources of FieldAccessingSolutionCloner I found out that I only needed to override the method retrieveCachedFields(...) or constructCloneCollection(...) so I tried to extend FieldAccessingSolutionCloner but then I need a public no-args-constructor. There I dont know how to initialise the field solutionDescriptor in the no-args-constructor to use my ExtendedFieldAccessingSolutionCloner as solution cloner.
If the generic solution cloner decided to clone that List, there is probably a good reason for it do so: one of the the elements in that list probably has a reference to a planning entity or the planning solution - and therefore the entire list needs to be planning cloned.
If that's not the case, this is a bug in OptaPlanner. Please provide the classes source code of the class with that field and the CustomListImpl class too, so we can reproduce and fix it.
To supply a custom SolutionCloner, follow the docs which will show something like this (but this is a simple case without chained variables, so it's easy to get right, but solution cloning is notoriously difficult!).
#PlanningSolution(solutionCloner = VaccinationSolutionCloner.class)
public class VaccinationSolution {...}
public class VaccinationSolutionCloner implements SolutionCloner<VaccinationSolution> {
#Override
public VaccinationSolution cloneSolution(VaccinationSolution solution) {
List<PersonAssignment> personAssignmentList = solution.getPersonAssignmentList();
List<PersonAssignment> clonedPersonAssignmentList = new ArrayList<>(personAssignmentList.size());
for (PersonAssignment personAssignment : personAssignmentList) {
PersonAssignment clonedPersonAssignment = new PersonAssignment(personAssignment);
clonedPersonAssignmentList.add(clonedPersonAssignment);
}
return new VaccinationSolution(solution.getVaccineTypeList(), solution.getVaccinationCenterList(), solution.getAppointmentList(),
solution.getVaccinationSlotList(), clonedPersonAssignmentList, solution.getScore());
}
}

Best way to define model using AndroidAnnotations #Rest and Kotlin?

I am totally new to Android and Kotlin and I was looking into Android Annotations.
I managed to decode a JSON response using the following code:
class ExampleModel {
#JvmField
final var id: Int = 0
lateinit var title: String
var description: String? = null
var author: Author? = null
}
#Rest(
rootUrl = "...",
converters = [MappingJackson2HttpMessageConverter::class]
)
interface ExampleClient {
#Get("/promotions")
fun getModels(): List<ExampleModel>
}
Now it does work but there are a couple of questions I'd like to ask.
Is it possible to use data classes? I tried but I kept getting an error from MappingJackson2HttpMessageConverter saying that there was no constructor available.
Is it somehow possible to just ignore extra keys that might appear in the JSON? Let's say that I am not interested in the author data for now, is there a way to just remove its declaration without having the decoding fail with "unexpected key"?
Consider that I usually work with Swift so if you could point me to the "Codable" equivalent in Kotlin I would really appreciate it.
Cheers
Kotlin Data classes don't have default constructor which is usually required by json deserialization libraries. Any data class require at least one constructor argument, but you can work around it. Define default values, you can use null. For example:
data class Pojo(val name: String? = null, val age: Int? = null)
Such code will allow to use Pojo() constructor. It should work, but it's better to use json deserializer that is more kotlin native or generate data classes with AutoValue.
Jackson that you're using here allows to ignore fields with #JsonIgnoreProperties.
If you're learning Android, don't start from Android Annotations if you don't have to. It's not very popular or modern solution. I used it in few projects back in the day, those were very difficult to maintain or to introduce new developers. Look into android architecture components and jetpack - google made few nice code labs. Also for json pick Moshi or Gson.

Properly Reading and Understanding Documentation

While looking at examples of Kotlin code I cam across this:
fun main(args: Array<String>) {
val myList = List(3) {it + 1}
println(myList)
}
I understand what it does, but I didn't know a List could be constructed this way. When I reference the documentation (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html) to see other possible ways to construct a List, I don't see any constructors at all. I can only assume I'm not looking in the right spot.
How do I go about properly reading documentation for Kotlin? Shouldn't everything pertaining to a List be contained in one place?
Since List is only an interface, it cannot have any constructors - it's a global function.
Most IDEs (like IntelliJ) should let you "ctrl+left click" or otherwise navigate to the source.
This is the related package: kotlin.collections.
And function you refer to: List.

Retrofit/Gson how to create type adapters dynamically

I learned from one example, so I am not sure if this is the optimal way or not, but anyways, I use the following code. I create one Retrofit instance and use it for all requests.
Since there are many methods, there are many types of data. It seems that I can create adapters (json -> my data class) automatically simply by adding annotations. But I needed more control (inheritance: the data classes have shared fields, dependency: some fields may not exist depending on other field's values), so I created a custom adaptor for each of the classes. So, currently my code is like this:
if (instance == null)
{
val gson = GsonBuilder()
.registerTypeAdapter(myClass1::class.java, myClassDeserialiser1())
.... (tens of this) ....
.registerTypeAdapter(myClass30::class.java, myClassDeserialiser30())
.create()
instance = Retrofit.Builder().
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(MyAPIs::class.java);
}
return instance
The problem above is that I am creating instances of all parsers at the same time in advance. This may be inefficient. I wish I could create them when they are first needed. Is that possible?
You can add a #JsonAdapter annotation to your class definition in lieu of calling registerTypeAdapter. I can't comment on its efficiency, but it keeps the adapter info tied to the object instead of the creation of your Gson object, which sounds like what you want.

Simple Jackson Array string addition

I am trying to convert GSON to jackson I have a method that returns a gson JsonObject. However it only creates a JsonArray, and returns that so I assume there is a simple casting there. So what would be the Jackson Equivalent? Now the method only adds one string at a time. So I need something like this:
JsonNode node = new JsonNode();
node.add("String 1");
node.add("String 2');
but would come out like this:
["String 1","String 2"]
I could create a List and map it from there, but I want to do this raw.
This seems too simple as google has given me many suggestions that are far beyond what this simple exercise requires.
And if anyone has a nice blog to tutorial on how to convert Gson to Jackson that would be great.
it is a bit tricky - you create an array node through JsonNode factory method:
ArrayNode arrNode = (ArrayNode)new JsonNode().withArray("my_array"); // arg is arrray propertry name
arrNode.add("String 1");
arrNode.add("String 2');
If you just want to create ArrayNode, ObjectMapper has method createArrayNode(), along with createObjectNode(). You can then add entries to it, as well as add node itself into other arrays, or as property in ObjectNode.
Actual construction of nodes by mapper is done using configurable JsonNodeFactory; default implementation of which simple constructs one of standard implementation types like ObjectNode and ArrayNode.