I am trying to integrate Kotlin in an existing android Java project. After making the changes in the build and adding Kotlin to the project I can't find a solution to my AutoValue classes that have GsonTypeAdapter there doesn't seem to be support for this.
#AutoValue
public abstract class MediaObject implements Parcelable {
public static TypeAdapter<MediaObject> typeAdapter(Gson gson) {
return new AutoValue_MediaObject.GsonTypeAdapter(gson);
}
#SerializedName("mimetype")
public abstract String getMimeType();
#SerializedName("url")
public abstract String getUri();
}
My Gson builder:
GsonBuilder().registerTypeAdapterFactory(new AutoValueGsonTypeAdapterFactory())
Any suggestions how to resolve this or what to use instead?
Just dont use it. If it is for Retrofit, you can just use .addConverterFactory(GsonConverterFactory.create()) and the kotlin data class.In your case, you need to remove MediaObject java class, and create data class:
data class MediaObject(
#SerializedName("mimetype")
val mimetypeString:String,
#SerializedName("url")
val uri:String)
Related
Is there a possibility to modify Lombok's #Getter for one type of field? There is a MutableLiveData that is child of LiveData. I want Lombok to create getters for MutableLiveData fields that return LiveData not MutableLiveData. I hope you understand what I mean.
To picture what I'm talking about I am adding some code:
public class ViewModelAccount extends ViewModel {
private MutableLiveData<String> selectedLanguagesReadable = new MutableLiveData<>();
public LiveData<String> getSelectedLanguagesReadable() {
return selectedLanguagesReadable;
}
}
It is about MVVM pattern in Android and removing boilerplate code in ViewModels. Thanks.
This answer might help you,
#Getter(AccessLevel.NONE) private boolean hasObject;
public boolean hasObject() {
return hasObject;
}
i found it here Edit lombok getter method name for boolean member having prefix "has"
I'm getting a compilation build error when I add a MutableLiveData object to my view model in my Android Studio project. I'm not calling getUser() or setUser() anywhere yet and I added the exact same object to a different view model in my project and haven't gotten an error, so I'm not sure what the problem is.
Error:
error: Parceler: Unable to find read/write generator for type androidx.lifecycle.MutableLiveData<com.example.demometvtest1.User> for com.example.demometvtest1.RegisterViewModel.user
RegisterViewModel.java:
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
#Parcel
public class RegisterViewModel extends ViewModel {
public MutableLiveData<User> user = new MutableLiveData<>();
public void setUser(String user) {
return user;
}
public MutableLiveData<User> getUser() {
this.user.setValue(user);
}
}
The problem is the annotation #Parcel: you are trying to automatic generate writeToParcel() & createFromParcel() and the annotation processor doesn't find a read/write implementation for MutabileLiveData (that it's not parcelable).
Remove the annotation, make the class implement the parcelable interface and make your own implementation of parcelable metods writeToParcel() & createFromParcel() if you need It or simply remove the annotation.
I have developed app base on android data binding library: https://developer.android.com/topic/libraries/data-binding/index.html
class SignInViewModel extends BaseObservable {
#Bindable
public String getLogin() {
return login;
}
#Bindable
public String getPassword() {
return password;
}
}
and now I want to use ViewModelProviders from new library:
https://developer.android.com/topic/libraries/architecture/guide.html
SignInViewModel signInViewModel = ViewModelProviders.of(this).get(SignInViewModel.class);
How it combine? any idea? or should be combined these two libraries?
Edit
I change to:
class SignInViewModel extends ViewModel {
public ObservableField<String> login = new ObservableField<>("");
public ObservableField<String> password = new ObservableField<>("");
}
and now compiles, but question is: is it right way?
It's a known incompatibility. You can't extend BaseObservable and AndroidViewModel at the same time, so you can't use #Bindable making two-way data binding impossible*.
This will be fixed after arch components 1.0 final (on the data binding side).
*Edit: You can make your own ObservableViewModel: https://gist.github.com/JoseAlcerreca/4b66f9953d50b483d80e6b9ad7172685
Maybe this didn't exist when when the question was asked, but there is another option explained in this article: https://medium.com/google-developers/android-data-binding-observability-9de4ff3fe038
Basically instead of extending from BaseObservable you can implement android.databinding.Observable.
It's slightly more work as you need to also do the following:
Create this variable in your model class
private PropertyChangeRegistry registry = new PropertyChangeRegistry();
Implement the overriden methods like this
#Override
public void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
registry.add(callback);
}
#Override
public void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
registry.remove(callback);
}
Replace all the "BR" calls with these:
registry.notifyChange(this, BR.bar);
Everything else works the same as extending from BaseObservable. So I think maybe this is the solution that Jose might have been alluding to which probably wasn't available back then. It seems to work.
Update: As Eugene Brusov has mentioned, you can now use LiveData with data binding. This is what I'm doing now and it's much easier with less boilerplate. See https://developer.android.com/topic/libraries/data-binding/architecture.
It's possible with Android Studio 3.1 Canary 6 (https://androidstudio.googleblog.com/2017/12/android-studio-31-canary-6-is-now.html):
You can now use a LiveData object as an observable field in data binding expressions. The ViewDataBinding class now includes a new setLifecycle method that you need to use to use to observe LiveData objects.
You can find more details and sample in this Medium post.
This can be also solved using a wrapper:
class SignInViewModelWrapper extends ViewModel {
public final SignInViewModel model = new SignInViewModel();
}
class SignInViewModel extends BaseObservable {
#Bindable
public String getLogin() {
return login;
}
#Bindable
public String getPassword() {
return password;
}
}
You can then get the view model like this:
SignInViewModel signInViewModel = ViewModelProviders.of(this).get(SignInViewModelWrapper.class).model;
I tried using Retrofit on Android and I encountered this problem.
I want to get data in JSON from an API and convert it into a model in my app.
This is my model
public class A {
private String property1;
private int property2;
//default constructor, getter and setter below
}
This is my service
public interface TestService {
#GET("/a")
void getA(Callback<A> callback);
}
When I retrieve the data using TestService, it won't return an error but it will return an empty class of A.
If I change the property of class A to public, then it will be converted to the right object A.
EDIT QUESTION
This is the JSON example that I want to convert into model A
{
"property1" : "content",
"property2" : 1
}
Use Expose annotation on your private fields if you are using GSON.
Like :
#Expose
private String property1;
#Expose
private int property2;
If you want to use a different name for your variables, you can try SerializedName annotation like :
#Expose
#SerializedName("property1")
private String p1;
#Expose
#SerializedName("property2")
private int p2;
I think that should work, if not post your complete "A" class.
I am using Lombok for one of my apps.
I have a class declared with the annotation #Builder. The fields are annotated with #SerializedName("xxxxx") in order to support Gson.
However, one of the fields is a List so I would like to use the #Singular annotation for them, but looks like the lib doesn't know about this annotation.
#Builder
public class ProductForm {
#SerializedName("title") private String title;
#SerializedName("description") private String description;
#SerializedName("images") private List<ImageForm> imageFormList;
#SerializedName("active") private boolean active;
}
Does anyone know why?
Doc here
Using lombok 1.16.4 and your code (used #lombok.Builder not the deprecated one) I've no compile error when adding #lombok.Singular to imageFormList in your code.
So you probably forgot to import #lombok.Singular or used an old version of lombok.