To begin with I am not sure how to express the issue but I am really stuck (I read this Why can I still make changes to this final variable? but it didn't help). I use CodenameOne framework but I am not sure too the issue spurts from it, it could be general java.
In my App I am sending Reports to the server. It works great.
The method is as follows in the Report class:
public void sendAsync(SuccessCallback<Report> onSuccess) {
// Update : With a shallow copy it does not work
// final Report currentReport = this;
// But with a deeper copy it does
final Report currentReport = clone(this);
final MultipartRequest request = new MultipartRequest() {
@Override
protected void readResponse(InputStream input) throws IOException {
// ... Does stuff here on Report's attributes
// Here the variable currentReport changes during overlapping sendings
@Override
postResponse(){
// The goal is to use some attributes from the current report
// to be shown in a popup to remind the user what we sent
// BUT the as written above the currentReport changes during
// overlapping sendings so that what is shown to the user only
// deals with the lastest report and does not make sense.
onSuccess(currentReport);
}
}
} // end of sendAsync
I call it like this when the user presses the send button:
Report myReport = new Report();
myReport.photoPath.set(...);
myReport.id.set(...);
anotherMethod(myReport); // this passes myReport to sendAsync but never modifies it
// Here myReport has still the right attributes based on the parameters
myReport.sendAsync((sentReport) -> {/* does something else */});
The problem is that when the user presses the send button whereas a previous sending is going on, the previous sending takes the attributes of the following one and it is NOT what I want.
So I don't know where to search in my code, the variables are not static. How can I make previous currentReport not change when the sendings overlap ?
February 25th 2018's update
What I don't understand is why I have to create a deep copy of this
to make it work (the static Report clone(Report sourceReport)
method creates a new Report, sets its attributes with the ones of the passed in sourceReport, and returns the created Report) ?
Moreover when the user presses the button the following is done :
Report report = new Report();
report.photoPath.set(the_path_returned_from_the_camera);
report.otherAttributes.set(values);
report.sendAsync((sentReport) -> {
showConfirmationPopup(sentReport);
// However here report.photoPath returns a different path
// from sentReport.photoPath which surprises me. Why do they differ ?
System.out.println(report.photoPath.get()); //prints /home/a.jpg
System.out.println(sentReport.photoPath.get()); //prints /home/b.jpg
});
What I don't understand too is why within the lambda, report and sendReport do not have the same content when a deep copy is done (there were the same with a shallow copy) ?
The Report constructor works like :
public Report() {
this.location.set(null);
this.photoPath.set("");
...
this.connectionError = false;
}
Thank you very much in advance, I can provide more details if requested