I have class ITEM and I want to pass array (Item[] items) of this class from ACTIVITY to FRAGMENT. Activity and fragment use Android Annotations.
public class Item implements Parcelable {
public int id;
public String code;
public Item() {
}
public Item(int id, String code) {
this.id = id;
this.code = code;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
protected Item(Parcel in) {
id = in.readInt();
code = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(code);
}
#SuppressWarnings("unused")
public static final Creator<Item> CREATOR = new Creator<Item>() {
#Override
public Item createFromParcel(Parcel in) {
return new Item(in);
}
#Override
public Item[] newArray(int size) {
return new Item[size];
}
};
}
Now I do it old way - I do not use parcelable, because I do not have to, but it seems that I canĀ“t pass same argument to fragment with Android Annotations (I may be wrong).
Activity:
new ItemFragment(items)
Fragment:
public class ItemFragment extends Fragment {
public ItemFragment (Item[] items) {
this.items= items;
}
}
Related
I am currently trying to pass some data from my fragment to an activity. I am passing some parameter, and also an arraylist of a model class. I already make sure that the arraylist before I passed it is not null, since I am able to print out the value in log. But it become null in the called activity.
Here is the model class:
public class Product implements Parcelable {
String code, id, status, is_expired;
public Product() {}
public Product(String code, String id, String status, String is_expired) {
this.code = code;
this.id = id;
this.status = status;
this.is_expired = is_expired;
}
public Product(Parcel in) {
code = in.readString();
id = in.readString();
status = in.readString();
is_expired = in.readString();
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getIs_expired() {
return is_expired;
}
public void setIs_expired(String is_expired) {
this.is_expired = is_expired;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(code);
dest.writeString(id);
dest.writeString(status);
dest.writeString(is_expired);
}
public static final Parcelable.Creator<Product> CREATOR = new Parcelable.Creator<Product>() {
public Product createFromParcel(Parcel in) {
return new Product(in);
}
public Product[] newArray(int size) {
return new Product[size];
}
};
}
Here is the caller:
intent.putExtra("product", productList);
Here is how retrieve the data:
ArrayList<Product> productList = getIntent().getParcelableExtra("product");
What am I doing wrong here?
Try this .
intent.putParcelableArrayListExtra("product", productList);
And next Activity .
ArrayList<Product> productList = getIntent().getParcelableArrayListExtra("product");
I am sending data from one activity to another activity from different packages.I applied intent to send and receive data.
For sending single value its working but now I want to send object via intent so I implemented Parcelable but I am getting error that class not found.
Here is my code.....
Sender side Classes :-
Sender MainActivity
public class MainActivity extends AppCompatActivity {
Button click;
Student student = new Student(01,"Anjali");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
click = (Button)findViewById(R.id.app1);
click.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent act = new Intent("com.gov.printer");
act.putExtra("data",student);
startActivity(act);
}
});
}
}
Student Sender class
public class Student implements Parcelable {
int id;
String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static Creator<Student> getCREATOR() {
return CREATOR;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
}
public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>()
{
#Override
public Student createFromParcel(Parcel source) {
return new Student(source);
}
#Override
public Student[] newArray(int size) {
return new Student[size]; }
};
private Student(Parcel in){
}
}
Receiver side Classes:-
Student receiver class
public class Student implements Parcelable{
int id;
String name;
public int get Id() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static Creator<Student> getCREATOR() {
return CREATOR;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
}
public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>()
{
#Override
public Student createFromParcel(Parcel source) {
return new Student(source);
}
#Override
public Student[] newArray(int size) {
return new Student[size];
}
};
private Student(Parcel in){
this.name = in.readString();
this.id = in.readInt();
}
}
Receiver MainActivity
public class MainActivity extends AppCompatActivity {
TextView getdata;
String TAG ="Main";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getdata = (TextView)findViewById(R.id.textapp);
Intent in = getIntent();
if (in.getAction().equals("com.gov.printer"));
{
Student student = in.getParcelableExtra("data");
Log.e(TAG,"data is"+student);
getdata.setText("name:-" +student.getName()+"\n"
+"ID:- " +student.getId());
}
}
You can achieve like this
Student class:
package com.ex.utils;
import android.os.Parcel;
import android.os.Parcelable;
public class Student implements Parcelable {
int id;
String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.name);
}
public Student() {
}
protected Student(Parcel in) {
this.id = in.readInt();
this.name = in.readString();
}
public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() {
#Override
public Student createFromParcel(Parcel source) {
return new Student(source);
}
#Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
Sender:
Intent i = new Intent("");
i.putExtra("data", student);
Receiver:
Student student = getIntent().getParcelableExtra("data");
I have an object with a couple of Strings, one int and another object which has 4 inner objects. All of them implementing Parcelable. In order to generate the boilerplate code, I used Parcelable plugin from Android studio.
Even though all the objects are parcelable, I'm getting the following error: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: AlbumTrackResponse
Here's how the POJOs look like:
Main object:
public class AlbumTrackResponse implements Parcelable {
private String id;
private String albumId;
private String position;
private String title;
private int rate;
private AllServices services;
public AllServices getServices() {
return services;
}
public void setServices(AllServices services) {
this.services = services;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAlbumId() {
return albumId;
}
public void setAlbumId(String albumId) {
this.albumId = albumId;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getRate() {
return rate;
}
public void setRate(int rate) {
this.rate = rate;
}
protected AlbumTrackResponse(Parcel in) {
id = in.readString();
albumId = in.readString();
position = in.readString();
title = in.readString();
rate = in.readInt();
services = (AllServices) in.readValue(AllServices.class.getClassLoader());
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(albumId);
dest.writeString(position);
dest.writeString(title);
dest.writeInt(rate);
dest.writeValue(services);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<AlbumTrackResponse> CREATOR = new Parcelable.Creator<AlbumTrackResponse>() {
#Override
public AlbumTrackResponse createFromParcel(Parcel in) {
return new AlbumTrackResponse(in);
}
#Override
public AlbumTrackResponse[] newArray(int size) {
return new AlbumTrackResponse[size];
}
};
}
Inner object with 4 objects
public class AllServices implements Parcelable {
private GigRevService gigrev;
private AppleService apple;
private GoogleService google;
private SpotifyService spotify;
protected AllServices(Parcel in) {
gigrev = (GigRevService) in.readValue(GigRevService.class.getClassLoader());
apple = (AppleService) in.readValue(AppleService.class.getClassLoader());
google = (GoogleService) in.readValue(GoogleService.class.getClassLoader());
spotify = (SpotifyService) in.readValue(SpotifyService.class.getClassLoader());
}
#Override
public int describeContents() {
return 0;
}
public GigRevService getGigrev() {
return gigrev;
}
public void setGigrev(GigRevService gigrev) {
this.gigrev = gigrev;
}
public AppleService getApple() {
return apple;
}
public void setApple(AppleService apple) {
this.apple = apple;
}
public GoogleService getGoogle() {
return google;
}
public void setGoogle(GoogleService google) {
this.google = google;
}
public SpotifyService getSpotify() {
return spotify;
}
public void setSpotify(SpotifyService spotify) {
this.spotify = spotify;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(gigrev);
dest.writeValue(apple);
dest.writeValue(google);
dest.writeValue(spotify);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<AllServices> CREATOR = new Parcelable.Creator<AllServices>() {
#Override
public AllServices createFromParcel(Parcel in) {
return new AllServices(in);
}
#Override
public AllServices[] newArray(int size) {
return new AllServices[size];
}
};
}
The inner objects from here contain just string items.
Here's how I pass the ArrayList to the bundle:
bundle.putParcelableArrayList(MediaPlayerService.TRACK_LIST, trackList);
I'm passing the items from an Activity to a Service. Any ideas why I'm getting this error?
EDIT: Implementation of service classes
public class GoogleService implements Parcelable {
private String name;
private String uri;
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected GoogleService(Parcel in) {
name = in.readString();
uri = in.readString();
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(uri);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<GoogleService> CREATOR = new Parcelable.Creator<GoogleService>() {
#Override
public GoogleService createFromParcel(Parcel in) {
return new GoogleService(in);
}
#Override
public GoogleService[] newArray(int size) {
return new GoogleService[size];
}
};
}
This looks extremly strange
this.services = in.readParcelable(getClass().getClassLoader());
You are pointing out to the wrong class loader. You have to use it like this
this.services = (AllServices)in.readParcelable(AllServices.class.getClassLoader());
Besides that, I am always using this site http://www.parcelabler.com/ to quickly generate my Parceables. Or you could use it like this
services = (AllServices) in.readValue(AllServices.class.getClassLoader());
Here:
protected AllServices(Parcel in) { this.gigrev = in.readParcelable(getClass().getClassLoader());
this.apple = in.readParcelable(getClass().getClassLoader());
this.google = in.readParcelable(getClass().getClassLoader());
this.spotify = in.readParcelable(getClass().getClassLoader()); }
Replace it with
protected AllServices(Parcel in) { this.gigrev = in.readParcelable(GigRevService.class.getClassLoader());
this.apple = in.readParcelable(AppleService.class.getClassLoader());
this.google = in.readParcelable(GoogleService.class.getClassLoader());
this.spotify = in.readParcelable(SpotifyService.class.getClassLoader()); }
And replace:
this.services = in.readParcelable(getClass().getClassLoader());
With:
this.services = in.readParcelable(AllServices.class.getClassLoader());
Also can you show the GoogleService etc classes? Each inner object's class must have a Parcelable creator also and implement the Parcelable interface as well.
i have a Parent class implementing parcelable and a child extending parent also implementing parcelable. My code is attached below. I get a runtime ClassCastException. What am I missing?
Thanks,
Parent Class:
public class Follower implements Parcelable{
private long id;
private String fullName;
public Follower() {
}
public Follower(String fullName) {
this.fullName = fullName;
}
public long getId(){
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getFullName());
}
protected Follower(Parcel in){
setFullName(in.readString());
}
public static final Parcelable.Creator<Follower> CREATOR =
new Parcelable.Creator<Follower>() {
public Follower createFromParcel(Parcel in) {
return new Follower(in);
}
public Teen[] newArray(int size) {
return new Teen[size];
}
};
}
The Child Class
public class Teen extends Follower
implements Parcelable{
public Teen(){
super();
}
public Teen( String fullName, String birthDate) {
super(fullName);
this.birthDate = birthDate;
}
private String birthDate;
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate){
this.birthDate = birthDate;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString (birthDate);
}
private Teen(Parcel in){
super(in);
birthDate = in.readString();
}
public static final Parcelable.Creator<Teen> CREATOR =
new Parcelable.Creator<Teen>() {
public Teen createFromParcel(Parcel in) {
return new Teen(in);
}
public Teen[] newArray(int size) {
return new Teen[size];
}
};
}
On the server, I create a Teen/Follower like below. The teen and follower clasess are copied to the server without the parcelable implementation.
public Follower getData()
{
if (logic to see if the user is a teen){
Teen t = new Teen( "Full Name", "1:1:1960");
return t;
}
else
{
Follower f = new Follower("Full Name");
return f;
}
}
On the client
I do get the Follower in the client code. I have checked by accessing the Follower class methods. It works. However when I do something like this I get a ClassCastException at runtime.
if(logic to see if it is a teen)
{
Teen t = (Teen) follower;
}
I am sure it is something small that I am missing but am at loss. Any help will be appreciated. Thanks,
Change this:
public class Teen extends Follower
implements Parcelable{
to this:
public class Teen extends Follower{
You don't have to reimplement the parcelable in child, because it inherit from the parent. I'm not sure, but when you create a Teen it implements it's own parcelable data-type, and it isn't in hierarchical structure with it's parent parcelable data-type.
I'm trying to parcel an object which contains some string/int variables and an object variable. The strings and int's are working, but not the nested object. I understand I would have to it also parcelable, but I'm apparently doing something wrong=. In my nested class, the writeToParcel method gets called (I check with a Log.d() call), but the createFromParcel() doesn't. I end up getting a null object. This is my simplified code:
public class MyClass implements Parcelable {
public MyClass() {
}
private Integer id;
private String name;
private MyOtherClass otherClass = new MyOtherClass();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public OtherClass getOtherClass() {
return otherClass;
}
public void setOtherClass(OtherClass otherClass) {
this.otherClass = otherClass;
}
public static final Parcelable.Creator<MyClass> CREATOR
= new Parcelable.Creator<MyClass>() {
public MyClass createFromParcel(Parcel in) {
return new MyClass(in);
}
public MyClass[] newArray(int size) {
return new MyClass[size];
}
};
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(id);
dest.writeParcelable(otherClass, flags);
}
private MyClass(Parcel in) {
name = in.readString();
id = in.readInt();
otherClass = (OtherClass) in.readParcelable(OtherClass.class.getClassLoader());
}
}
class MyOtherClass implements Parcelable {
public OtherClass() {
}
private String resourcePreviewURL;
public String getResourcePreviewURL() {
return resourcePreviewURL;
}
public void setResourcePreviewURL(String resourcePreviewURL) {
this.resourcePreviewURL = resourcePreviewURL;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
Log.d("parcel", "write to parcel"); // this gets called
out.writeString(resourcePreviewURL);
}
public static final Parcelable.Creator<MyOtherClass> CREATOR
= new Parcelable.Creator<MyOtherClass>() {
public MyOtherClass createFromParcel(Parcel in) {
Log.d("parcel", "create from parcel"); // this doesn't get called
return new MyOtherClass(in);
}
public ResourcePreviews[] newArray(int size) {
return new ResourcePreviews[size];
}
};
private OtherClass(Parcel in) {
Log.d("parcel", "read from parcel"); // this doesn't get called
resourcePreviewURL = in.readString();
}
}
I solved this by changing the order in which I write/read from the Parcel. I made the dest.writeParcelable(otherClass, flags); and the otherClass = (OtherClass) in.readParcelable(OtherClass.class.getClassLoader()); calls to be the first in their methods and it started working. Is that an issue?
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(otherClass, flags);
dest.writeString(name);
dest.writeInt(id);
}
private MyClass(Parcel in) {
otherClass = (OtherClass) in.readParcelable(OtherClass.class.getClassLoader());
name = in.readString();
id = in.readInt();
}