I am very beginner in Android and Parcelable interface . I just want to send
private XMPPTCPConnection xmpptcpConnection;
this above XMPPTCPConnection object from one Activity to another Activity.But I am error getting error as:
java.lang.RuntimeException: Parcel: unable to marshal value org.jivesoftware.smack.tcp.XMPPTCPConnection#342f1d60
at android.os.Parcel.writeValue(Parcel.java:1337)
at com.example.rahul.samplesmack.Def.writeToParcel(Def.java:31)
Below is my java code:
public class Def implements Parcelable {
private XMPPTCPConnection xmpptcpConnection;
public void setXmpptcpConnection(XMPPTCPConnection xmpptcpConnection)
{
this.xmpptcpConnection = xmpptcpConnection;
}
public XMPPTCPConnection getXmpptcpConnection()
{
return xmpptcpConnection;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(xmpptcpConnection); //I am getting Error here!!!!!
}
public Def(){}
protected Def(Parcel in) {
xmpptcpConnection = (XMPPTCPConnection) in.readValue(XMPPTCPConnection.class.getClassLoader());
}
public static final Creator<Def> CREATOR = new Creator<Def>() {
#Override
public Def createFromParcel(Parcel in) {
return new Def(in);
}
#Override
public Def[] newArray(int size) {
return new Def[size];
}
};
}
Related
I have a function that returns void
public interface IProductService {
void delete(String id);
}
Generic method
public interface IRequestHandler<C , R> {
R handler(C c);
Class<C> commandType();
}
Implementation of generic interface
#Singleton
public record DeleteProductCommandHandler(IProductService iProductService)
implements IRequestHandler<DeleteProductCommand, Void> {
#Override
public Void handler(DeleteProductCommand deleteProductCommand) {
return iProductService.delete(deleteProductCommand.id);
}
#Override
public Class<DeleteProductCommand> commandType() {
return DeleteProductCommand.class;
}
}
How can I use void in IRequestHandler<DeleteProductCommand, Void> so that I can map void from iProductService.delete(deleteProductCommand.id);
Option 1:
Just return null:
#Override
public Void handler(DeleteProductCommand deleteProductCommand) {
iProductService.delete(deleteProductCommand.id);
return null;
}
Option 2:
Update the IProductService::delete method to return something meaningful, e.g. a boolean value like Collection::remove does:
public interface IProductService {
boolean delete(String id);
}
#Singleton
public record DeleteProductCommandHandler(IProductService iProductService)
implements IRequestHandler<DeleteProductCommand, Boolean> {
#Override
public Boolean handler(DeleteProductCommand deleteProductCommand) {
return iProductService.delete(deleteProductCommand.id);
}
#Override
public Class<DeleteProductCommand> commandType() {
return DeleteProductCommand.class;
}
}
The source is like this :
public class NavUIStatus implements Parcelable {
public static final Creator<NavUIStatus> CREATOR = new
Creator<NavUIStatus()
{
public NavUIStatus createFromParcel(Parcel in) {
return new NavUIStatus(in);
}
public NavUIStatus[] newArray(int size) {
return new NavUIStatus[size];
}
};
private NavUIStatus(Parcel in){
...
in.readTypedList(this.laneInfos, LaneInfo.CREATOR);
}
}
and when decompile this class in the android studio, the class is shown as this:
public class NavUIStatus implements Parcelable {
public static final Creator<NavUIStatus> CREATOR = new Creator() {
public NavUIStatus createFromParcel(Parcel in) {
return new NavUIStatus(in, null);
}
public NavUIStatus[] newArray(int size) {
return new NavUIStatus[size];
}
};
}
so, why there is null parameter in the NavUIStatus(in, null) ?
thanks.
I've created a custom implementation of Call<T>, here is the custom class without the custom code, just the forward code for you to see.
public class CachedCall<T> implements Call<T> {
private final Call<T> delegate;
public CachedCall(Call<T> delegate) {
this.delegate = delegate;
}
#Override
public Response<T> execute() throws IOException {
return delegate.execute();
}
#Override
public void enqueue(Callback<T> callback) {
delegate.enqueue(callback);
}
public void enqueueWithCache(final CachedCallback<T> callback) {
delegate.enqueue(callback);
}
#Override
public boolean isExecuted() {
return delegate.isExecuted();
}
#Override
public void cancel() {
delegate.cancel();
}
#Override
public boolean isCanceled() {
return delegate.isCanceled();
}
#Override
public Call<T> clone() {
return new CachedCall<>(delegate.clone());
}
#Override
public Request request() {
return delegate.request();
}
}
And then in my ApiService, I used this custom implementation on some of my call, and the default one on some other, exemple:
public interface APIService {
#GET("categories")
Call<List<Categorie>> categories(#Query("tag") String tag);
#GET("categories/{categorie}/quotes")
CachedCall<List<Gif>> gifs(#Path("categorie") String categorie);
When methods with the custom one are called, I got a crash:
Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for CustomClass.
Tried:
* retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
* retrofit2.ExecutorCallAdapterFactory
at retrofit2.Retrofit.nextCallAdapter(Retrofit.java:237)
at retrofit2.Retrofit.callAdapter(Retrofit.java:201)
at retrofit2.ServiceMethod$Builder.createCallAdapter(ServiceMethod.java:232)
... 21 more
Do I need to register my custom implementation with Retrofit somewhere?
I've solved my own issue.
You need to create and register your own CallAdapter.Factory:
public class CachedCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
public CachedCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
#Override
public CallAdapter<Call<?>> get(final Type returnType, final Annotation[] annotations, final Retrofit retrofit) {
if (getRawType(returnType) != CachedCall.class) {
return null;
}
final Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);
return new CallAdapter<Call<?>>() {
#Override public Type responseType() {
return responseType;
}
#Override public <R> Call<R> adapt(Call<R> call) {
return new CachedCall<>(callbackExecutor, call, responseType, retrofit, annotations);
}
};
}
}
And then register it when you create your Retrofit instance:
retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(URL)
.addCallAdapterFactory(new CachedCallAdapterFactory(new DefaultExecutor()))
.build();
Your DefaultExecutor just need to run its Runnable
private class DefaultExecutor implements Executor {
#Override
public void execute(#NonNull Runnable runnable) {
runnable.run();
}
}
I want to send an object from an activity to another using Parcelable in the class. I have a Parcelable class that has two strings and an Exception as attributes.
public class ReportErrorVO implements Parcelable {
private String titleError;
private String descriptionError;
private Exception exceptionError;
public ReporteErrorVO(Parcel in) {
titleError = in.readString();
descriptionError = in.readString();
exceptionError = ????; //What do I put here?
}
public ReporteErrorVO() {
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(titleError);
dest.writeString(descriptionError);
dest.writeException(exceptionError);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public ReportErrorVO createFromParcel(Parcel in) {
return new ReportErrorVO(in);
}
public ReportErrorVO[] newArray(int size) {
return new ReportErrorVO[size];
}
};
#Override
public int describeContents() {
return 0;
}
//Getter and setters atributes...
}
What can I do to set the exception in the parcelable attribute?
You can use readException method in.readException() and this method will throw the exception if it had been written to the parcel, so you may catch it and save to your variable.
try {
in.readException();
} catch (Exception e){
exceptionError = e;
}
Note that this method only supports limited types of exceptions
The supported exception types are:
* BadParcelableException
* IllegalArgumentException
* IllegalStateException
* NullPointerException
* SecurityException
* NetworkOnMainThreadException
Ok, doing it this way helped me to get things working: Send the exception on an array.
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mTitleError);
dest.writeString(mDescriptionError);
Exception[] exceptions = new Exception[1];
exceptions[0] = mExceptionError;
dest.writeArray(exceptions);
}
public ReportErrorVO(Parcel in) {
mTitleError = in.readString();
mDescriptionError = in.readString();
Object[] exceptions = in.readArray(Exception.class.getClassLoader());
mExceptionError = (Exception) exceptions[0];
}
Wrote a class that helps pass my object, was working fine until i wanted to pass a more generic object myself.
public class StepParceble implements Parcelable {
private Step mStep;
private JSONObject mStepData;
private onScreen mOnScreen;
public StepParceble(Step step, JSONObject stepData, onScreen onScreen) {
setmStep(step);
setmStepData(stepData);
setmOnScreen(onScreen);
}
public StepParceble(Parcel parcel){
}
public onScreen getmOnScreen() {
return mOnScreen;
}
public void setmOnScreen(onScreen mOnScreen) {
this.mOnScreen = mOnScreen;
}
public void setmStep(Step mStep) {
this.mStep = mStep;
}
public void setmStepData(JSONObject mStepData) {
this.mStepData = mStepData;
}
public JSONObject getmStepData() {
return mStepData;
}
public Step getmStep() {
return mStep;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
try {
dest.writeArray(new Object[]{mStep, mStepData,mOnScreen});
} catch (Exception e) {
}
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public StepParceble createFromParcel(Parcel in) {
return new StepParceble(in);
}
public StepParceble[] newArray(int size) {
return new StepParceble[size];
}
};
}
it return a null pointer on getting any of those values.
Passing the data as
StepParceble stepParceble = new StepParceble(step, stepData, onScreen);
Intent uiIntent = new Intent(context, UIActivity.class).putExtra(UiControlTrier.STEP_KEY,stepParceble);
You didn't provide means to read fields from your parcelable when you've overridden the constructor
public StepParceble(Parcel parcel){
//add methods to populate fields from parcel
}
You can use Android Studio plugins to do this for you:
https://github.com/mcharmas/android-parcelable-intellij-plugin
Also, if your class has complex-type fields (like Step in your case), those should be Parcelable too