I created a POJO model and did not call it out.
This is the code to run it.
DataObjectSelectGarage selectGarage = ...;
TextView.setText(selectGarage.getGaragename());
Do not know if it can run this way?
this is model
public class DataObjectSelectGarage implements Serializable {
#SerializedName("Garage_id")
private int id;
public int getGarage_id() {
return id;
}
public void setgetGarage_id(String getGarage_id) {
this.id = id;
}
#SerializedName("Garagename")
private String name;
public String getGaragename() {
return name;
}
public void setGaragename(String name) {
this.name = name;
}
}
public void setgetGarage_id(String getGarage_id) {
this.id = id;
}
The above set method assigning Id = id instead of id= getGarage_id
This cannot work this way
DataObjectSelectGarage selectGarage;
TextView.setText(selectGarage.getGaragename());
As DataObjectSelectGarage is not initialized. You need to initialize it first.
Secondly in code you posted there are multiple logical bugs like you are passing UserId to HTTP request param without assigning value to it. Secondly without pasring response trying to present it to user.
#Override
public void onResponse(String response) {
/*DataObjectSelectGarage dataObjectSelectGarage = new
DataObjectSelectGarage();
String test1 = dataObjectSelectGarage.getGaragename();*/
tvTest.setText(selectGarage.getGaragename());
Log.d("Selectgarage",response.toString());
}
you need to parse the response string and then after initializing model object and setting values in it use it to show data on view.
Related
I have a class Data with list and two variable (id and name). I am replacing the variable with list values. First time in the list will be the new values of the id and name. After removing the id and name, the request object will contain only dataList. But the issue is the variable is being used in many places. I am thinking of creating the setter of the id and name properties in the Request object.
I created the getter and but not sure how to create the setter such that I add items to list for the same object. Also, how to override builder for those two fields alone. Assume the request object is big as well.
Class Request
#Builder
#Getter
public class Request {
private String id; //need to removed
private String name; //need to removed
private List<Data> dataList;
public String getId() {
return (dataList != null) ? dataList.get(0).getId() : null;
}
public String getName() {
return (dataList != null) ? dataList.get(0).getName() : null;
}
}
Class Data:
public class Data {
private String id;
private String name;
}
When someone calls setId or setName, then the item at index 0 in the dataList should be updated.
How do I do the same for builder ?
Overriding Lombok's setter doesn't change the builder's behavior, you have to override them both. Let's start with the harder one:
Builder
Lombok's builder is easy to be overridden by defining the skeleton of the builder. The existing parts won't be generated and Lombok only completes the builder. Create athisstatic nested class in Request:
public static class RequestBuilder {
public final RequestBuilder id(final String id) {
this.id = id;
updateData(id, name, dataList);
return this;
}
public final RequestBuilder name(final String name) {
this.name = name;
updateData(id, name, dataList);
return this;
}
}
What is updateData? You need to update the dataList on each builder's method call. The method must be static otherwise the static builder cannot access it. Define it right in the Request class:
private static void updateData(final String id, final String name, List<Data> dataList) {
if (dataList == null) {
dataList = new ArrayList<>();
}
if (dataList.isEmpty()) {
dataList.add(new Data(id, name));
} else {
var data = dataList.get(0);
data.setId(id);
data.setName(name);
}
}
Your case when dataList is null is not handled, so I rather initialize it here for sure (hence the field cannot be final among the formal parameters of the method).
Setter
This is easy, you need to do basically the same thing like in the builder - just override the correct methods:
public final void setId(final String id) {
this.id = id;
updateData(id, getName(), dataList);
}
public final void setName(final String name) {
this.name = name;
updateData(getId(), name, dataList);
}
You are all set. For sake of simplicity, I have annotated the class Data with Lombok annotations #lombok.Data (beware of the name) and #AllArgsConstructor.
Test
It's always a good practice to write at least some units tests to cover and verify the behavior. I needed to annotate Request with #AllArgsConstructor to avoid calling the setters which are subjects of the test. I also would need some helpful methods for assertion and eliminating code duplication:
void assertRequestBeforeTest(final Request request) {
assertThat(request.getId(), nullValue());
assertThat(request.getName(), nullValue());
assertThat(request.getDataList(), hasSize(0));
}
void assertRequestAfterTest(final Request request, final String id, final String name) {
assertThat(request.getId(), is(id));
assertThat(request.getName(), is(name));
assertThat(request.getDataList(), notNullValue());
var data = request.getDataList().get(0);
assertThat(data, notNullValue());
assertThat(data.getId(), is(id));
assertThat(data.getName(), is(name));
}
And the tests:
#Test
void setter_onNullFields() {
var request = new Request(null, null, new ArrayList<>());
assertRequestBeforeTest(request);
request.setId("id-new");
request.setName("name-new");
assertRequestAfterTest(request, "id-new", "name-new");
}
#Test
void setter_onExistingFields() {
var request = new Request("id", "name", new ArrayList<>());
assertRequestBeforeTest(request);
request.setId("id-new");
request.setName("name-new");
assertRequestAfterTest(request, "id-new", "name-new");
}
#Test
void builder() {
var requestBuilder = Request.builder().dataList(new ArrayList<>());
var request = requestBuilder.id("id-new").name("name-new").build();
assertRequestAfterTest(request, "id-new", "name-new");
}
You only need to override the set method and set values within the method
public void setId(String id) {
if (dataList == null) {
dataList = new ArrayList(2);
}
if (null == dataList.get(0)) {
dataList.add(0, new Data());
}
dataList.get(0).setId(id);
}
If many places are calling the Request object. You can replace the setter of the id and name properties in the Request object. When rewriting the setter method of the id and name properties in the Request object, you can call the setter method of the Data object to write
How can i update a field of a ListItem?
I have following POJO and ViewModel classes. Currently i am getting the complete list from LiveData object and then updating its data then re-setting the value of LiveData object, But I don't think this is the correct way to do it because to update just name of a single book i have to reset the complete LiveData Object.
Any other suggestion or Good practice to do it the correct way?
public class Book {
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class BookProvider extends AndroidViewModel {
private final MutableLiveData<List<Book>> booksData;
public BookProvider(#NonNull Application application) {
super(application);
booksData = new MutableLiveData<>();
}
public LiveData<List<Book>> getBooksData() {
return booksData;
}
public void updateBookName(int position, String name) {
final List<Book> books = booksData.getValue();
if (books != null && books.size() > position) {
books.get(position).setName(name);
}
booksData.setValue(books);
}
}
LiveData is just a container holding a reference to your data and notifying possible observer of changes. So as far as LiveData is concerned this is the best you can do.
However LiveData does't support molecular changes so every change may results in the entire list invalidating and redrawn. It is strongly suggested that you use a different method if you have lot of changes in data (like real-time applications).
I've been using Spring Data for saving entities to the mongo DB and my code at the moment looks like this:
I have a repo class:
public interface LogRepo extends MongoRepository<Log, String> {
}
and I have an Entity Log which looks like this:
#Document(
collection = "logs"
)
public class Log {
#Id
private String id;
private String jsonMessage;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getJsonMessage() {
return jsonMessage;
}
public void setJsonMessage(String jsonMessage) {
this.jsonMessage = jsonMessage;
}
}
and this work well for me, however this approach works only for the case if I want to save Log entities to "logs" collection. However it would be very nice for me to be able to save Log entity to different collections depending on the context. I mean it would be nice to define collection name in the runtime. Is it possible somehow?
Thanks, cheers
Try to use inheritance and define appropriate collection names in such way. May give you possibility to save in different collections but you will be still not able to specify dynamically collection names and resp. their amount at runtime.
#Document(
collection = "logs"
)
public class Log {
#Id
private String id;
private String jsonMessage;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getJsonMessage() {
return jsonMessage;
}
public void setJsonMessage(String jsonMessage) {
this.jsonMessage = jsonMessage;
}
}
#Document(
collection = "log_child"
)
public class LogChild extends Log{}
With the MongoOperations save method you can choose which class to use and
based on the class it will choose the appropriate collection.
#Document(collection = "collection_#{T(com.github.your_project.DBUtils).getCollectionName()}")
public Class Collection
You can change the name in real time using a static getter
#UtilityClass
public class DBUtils {
private String collectionName;
public String getCollectionName() {
return collectionName;
}
public void setCollectionName(String collectionName) {
DBUtils.collectionName = collectionName;
}
}
I got json like below:
{"examinationTypes":[{"ExaminationTypeVO":{"id":1,"name":"Badanie krwi"}},{"ExaminationTypeVO":{"id":2,"name":"Spirometria"}},{"ExaminationTypeVO":{"id":3,"name":"Wymaz"}},{"ExaminationTypeVO":{"id":4,"name":"Ciśnienie"}},{"ExaminationTypeVO":{"id":5,"name":"EKG"}},{"ExaminationTypeVO":{"id":6,"name":"Elektrowstrząsy"}},{"ExaminationTypeVO":{"id":7,"name":"Tomografia"}},{"ExaminationTypeVO":{"id":8,"name":"Lewatywa"}},{"ExaminationTypeVO":{"id":9,"name":"Aneskopia"}},{"ExaminationTypeVO":{"id":10,"name":"Rektoskopia"}},{"ExaminationTypeVO":{"id":11,"name":"Kolonoskopioa"}},{"ExaminationTypeVO":{"id":12,"name":"Echo serca"}},{"ExaminationTypeVO":{"id":13,"name":"Ablacja"}},{"ExaminationTypeVO":{"id":14,"name":"Badnaie dopplerowskie"}},{"ExaminationTypeVO":{"id":15,"name":"Kapilaroskopia"}}]}
I have defined types:
#JsonRootName(value="ExaminationTypeVO")
#JsonIgnoreProperties(ignoreUnknown = true)
public class ExaminationTypeVO {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and
public class ExaminationTypesVO {
private List<ExaminationTypeVO> examinationTypes;
public List<ExaminationTypeVO> getExaminationTypes() {
return examinationTypes;
}
public void setExaminationTypes(List<ExaminationTypeVO> examinationTypes) {
this.examinationTypes = examinationTypes;
}
When I am deserializing it like that:
ExaminationTypesVO l = m.readValue(result, ExaminationTypesVO.class);
I receive an wrapper object but the list inside contains objects of type ExaminationTypeVO with all properties set to null.
Can anybody help to figure it out?
Your issue is that you have an extra level of object that you are trying to deserialize. Trying to not be confusing as I explain this: you have an array of objects, those objects contain a single ExaminationTypeVO object.
If you are stuck with the structure of the JSON that you provided, then you will need to add another "level" to your deserialization. You can do this via a wrapper object inside of your ExaminationTypesVO class:
public class ExaminationTypesVO {
private List<ExaminationTypeVOWrapper> examinationTypes;
public List<ExaminationTypeVOWrapper> getExaminationTypes() {
return examinationTypes;
}
public void setExaminationTypes(List<ExaminationTypeVOWrapper> examinationTypes) {
this.examinationTypes = examinationTypes;
}
public static class ExaminationTypeVOWrapper {
private final ExaminationTypeVO examinationTypeVO;
#JsonCreator
public ExaminationTypeVOWrapper(#JsonProperty("ExaminationTypeVO") ExaminationTypeVO examinationTypeVO) {
this.examinationTypeVO = examinationTypeVO;
}
public ExaminationTypeVO getExaminationTypeVO() {
return examinationTypeVO;
}
}
}
If you have control over the JSON that you are deserializing, you can just remove the extra "level" (ExaminationTypeVO wrapping object) and not have to change your code. Your new JSON in this approach would look like:
{
"examinationTypes": [
{
"id": 1,
"name": "Badanie krwi"
}, ...
]
}
With either of these approaches you can remove both of the class-level annotations you have on ExaminationTypeVO.
I am returning an array of results with my json Objects, and I am trying to use my customObjectResponse class to pull out each of the fields within each of the objects... the problem it is expecting an object so how do I edit my class to allow it to take in an array of object to be able to then call the fields of each object... I am confused as to what needs to be added:
Here is a response example of what is being passed to be used:
[
{
itemId: 'dfsdfsdf343434',
name: 'tests',
picture: '6976-7jv8h5.jpg',
description: 'testy.',
dateUpdated: 1395101819,
}
]
Here is my response Object Class:
public class ObjResponse{
private String itemId;
private String name;
private String picture;
private String description;
private String location;
private int dateUpdated;
private String msg;
//gridview constructor
public ObjResponse(String picture) {
this.picture = picture;
}
//public constructor
public ObjResponse() {
}
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getDateUpdated() {
return dateUpdated;
}
public void setDateUpdated(int dateUpdated) {
this.dateUpdated = dateUpdated;
}
public String getMsg() {
return msg;
}
}
what I am trying, but is not working, even if I separate the classes into their own files:
Data passed in:
items: [{obj1: "A", obj2: ["c", "d"]}, {etc...}]
public class Response {
public class List<Custom> {
private List<Custom> items;
}
public class Custom {
private String obj1;
private List<Obj2> obj2;
}
public Class Obj2 {
private String letters;
}
}
I ended up just calling in the callback a list of the customObject and it did the job...
new Callback<List<ObjResponse>>() {
I originally had trouble getting an idea of how the OP solved his problem but, after days of debugging I have finally figured out how to solve this issue.
So you essentially have data in the format like so (JSON Array of JSON Objects):
[
{
...
}
]
Your class that models the data and contains the getter and setter methods are nothing more than your typical POJO.
public class Person implements Serializable {
#SerializedName("Exact format of your json field name goes here")
private String firstName;
// Getters and Setters....
}
In your interface that contains your RESTful annotations you want to convert your call from:
Before:
public interface APInterface {
#GET("SOME URL TO YOUR JSON ARRAY")
Call<Person>(...)
}
After:
public interface APInterface {
#GET("SOME URL TO YOUR JSON ARRAY")
Call<List<Person>>(...)
}
In your android activity you want to convert all calls in the form of Call<Person> to Call<List<Person>>
Finally when making the initial asynchronous request call, you will want to convert your callbacks like so.
call.enqueue(new Callback<List<Person>>() {
#Override
public void onResponse(Call<List<Person>> call, Response<List<Person>> response) {
if(response.isSuccessful()){
List<Person> person = response.body();
// Can iterate through list and grab Getters from POJO
for(Person p: person){...}
} else {
// Error response...
}
}
#Override
public void onFailure(Call<List<Person>> call, Throwable t) {...}
});
Hope this helps others whom are lost from the accepted answer above.
This can also work by just passing an array of response objects. So if this is your response object:
public class CustomUserResponse {
public String firstName;
public String lastName;
...
}
You can use related syntax, depending on how you use the callbacks. Such as:
new Callback<CustomUserResponse[]>(){
#Override
public void success(CustomUserResponse[] customUserResponses, Response rawResponse) {
}
#Override
public void failure(RetrofitError error) {
}
};
OR
public class GetUserCommand implements Callback<CustomUserResponse[]> { ...
Put simply, in every place where you normally replace T with a response class, replace it with an array, instead as in CustomUserResponse[].
NOTE: to avoid confusing errors, be sure to also use an array in the Retrofit interface definition:
#POST ( "/users" )
public void listUsers(#Body GetUsersRequest request, Callback<CustomUserResponse[]> callback);
You could try something like this
JSONObject jsonObject = new JSONObject(<your JSON string result>);
JSONArray jsonArray = jsonObject.getJSONArray();
//use GSON to parse
if (jsonArray != null) {
Gson gson = new Gson();
ObjResponse[] objResponse = gson.fromJson(jsonArray.toString(), ObjResponse[].class);
List<ObjResponse> objResponseList = Arrays.asList(objResponse);
}
This should definitely work.