I'm making a game, and I need to move a custom Object. To do that, I'm using a Parcelable to move data.
However, I'm having problems moving the data, and I don't know why.
This is Parcelable class:
public class Character implements Parcelable {
public static int day;
public static int now_food;
public static int now_water;
public static int use_food;
public static int use_water;
public static int health;
public static String name;
public static char status; // d = 병걸림, n = 정상
public static char status_live; //w = 죽음 l = 생존
public static String status_water ; // t = 목마름 v = 매우 목마름
public static String status_food ; // h = 배고픔 v = 매우 배고픔
public Character() {
}
public Character(Parcel in) {
}
public Character(int use_food, int use_water, int health, String name, char status) {
this.status = status;
this.use_food = use_food;
this.use_water = use_water;
this.health = health;
this.name = name;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(use_food);
dest.writeInt(use_water);
dest.writeInt(health);
dest.writeString(name);
}
public void readFromParcel(Parcel in) {
use_food = in.readInt();
use_water = in.readInt();
health = in.readInt();
name = in.readString();
}
public static final Creator<Character> CREATOR = new Creator<Character>() {
#Override
public Character createFromParcel(Parcel in) {
return new Character(in);
}
#Override
public Character[] newArray(int size) {
return new Character[size];
}
};
#Override
public int describeContents() {
return 0;
}
}
Here's my main code:
character1.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), Character1_Activity.class);
intent.putExtra("ch1info", ch1);
startActivity(intent);
}
});
I move this object with button's click event.
Finally, this is the Activity that wants to get object.
Bundle bundle = getIntent().getExtras();
final Character ch1 = bundle.getParcelable("ch1info");
TextView get_water = (TextView) findViewById(R.id.water_stat);
get_water.setText(ch1.Check_water(ch1));
Why doesn't my code work, and how can I fix it?
you need to move your code inside readFromParcel to public Character(Parcel in)
you can simply delete readFromParcel method, its useless.
updated constructor would be will be:
public Character(Parcel in){
use_food = in.readInt();
use_water = in.readInt();
health = in.readInt();
name = in.readString();
}
Update your Character class as below:
public class Character implements Parcelable {
public static int day;
public static int now_food;
public static int now_water;
public static int use_food;
public static int use_water;
public static int health;
public static String name;
public static char status; // d = 병걸림, n = 정상
public static char status_live; //w = 죽음 l = 생존
public static String status_water ; // t = 목마름 v = 매우 목마름
public static String status_food ; // h = 배고픔 v = 매우 배고픔
public Character() {
}
public Character(int use_food, int use_water, int health, String name, char status) {
this.status = status;
this.use_food = use_food;
this.use_water = use_water;
this.health = health;
this.name = name;
}
public Character(Parcel in) {
this.use_food = in.readInt();
this.use_water = in.readInt();
this.health = in.readInt();
this.name = in.readString();
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(use_food);
dest.writeInt(use_water);
dest.writeInt(health);
dest.writeString(name);
}
public static final Parcelable.Creator<Character> CREATOR = new Parcelable.Creator<Character>() {
#Override
public Character createFromParcel(Parcel in) {
return new Character(in);
}
#Override
public Character[] newArray(int size) {
return new Character[size];
}
};
#Override
public int describeContents() {
return 0;
}
}
Send Character object:
character1.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
// Object
Character ch1 = new Character(27,32,65,"name",'n');
Intent intent = new Intent(getActivity(), Character1_Activity.class);
intent.putExtra("ch1info", ch1);
startActivity(intent);
}
});
Retrieve Character object in your Character1_Activity.java:
Bundle bundle = getIntent().getExtras();
final Character ch1 = bundle.getParcelable("ch1info");
Log.d("Success", "Use water: " + ch1.use_water + "\nUse food:" + ch1.use_food
+ "\nHealth: " + ch1.health + "\nName: " + ch1.name + "\nStatus: " + ch1.status);
OUTPUT:
D/Success: Use water: 32
Use food:27
Health: 65
Name: name
Status: n
Hope this will help~
Related
In my application i'm trying to pass an parcelable array list to a sectioned recycler view adapter but inside the add method where we add sections it gives me required string error:
This is my parcelable class:
public class HostBean implements Parcelable {
public static final String EXTRA = ActivityMain.PKG + ".extra";
public static final String EXTRA_POSITION = ActivityMain.PKG + ".extra_position";
public static final String EXTRA_HOST = ActivityMain.PKG + ".extra_host";
public static final String EXTRA_TIMEOUT = ActivityMain.PKG + ".network.extra_timeout";
public static final String EXTRA_HOSTNAME = ActivityMain.PKG + ".extra_hostname";
public static final String EXTRA_BANNERS = ActivityMain.PKG + ".extra_banners";
public static final String EXTRA_PORTSO = ActivityMain.PKG + ".extra_ports_o";
public static final String EXTRA_PORTSC = ActivityMain.PKG + ".extra_ports_c";
public static final String EXTRA_SERVICES = ActivityMain.PKG + ".extra_services";
public static final int TYPE_GATEWAY = 0;
public static final int TYPE_COMPUTER = 1;
public int deviceType = TYPE_COMPUTER;
public int isAlive = 1;
public int position = 0;
public int responseTime = 0; // ms
public String ipAddress = null;
public String hostname = null;
public String hostsection = null;
public String hardwareAddress = NetInfo.NOMAC;
public String nicVendor = "Unknown";
public String os = "Unknown";
public HashMap<Integer, String> services = null;
public HashMap<Integer, String> banners = null;
public ArrayList<Integer> portsOpen = null;
public ArrayList<Integer> portsClosed = null;
public HostBean() {
// New object
}
public HostBean(Parcel in) {
// Object from parcel
readFromParcel(in);
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(deviceType);
dest.writeInt(isAlive);
dest.writeString(ipAddress);
dest.writeString(hostname);
dest.writeString( hostsection );
dest.writeString(hardwareAddress);
dest.writeString(nicVendor);
dest.writeString(os);
dest.writeInt(responseTime);
dest.writeInt(position);
dest.writeMap(services);
dest.writeMap(banners);
dest.writeList(portsOpen);
dest.writeList(portsClosed);
}
private void readFromParcel(Parcel in) {
deviceType = in.readInt();
isAlive = in.readInt();
ipAddress = in.readString();
hostname = in.readString();
hardwareAddress = in.readString();
nicVendor = in.readString();
os = in.readString();
hostsection=in.readString();
responseTime = in.readInt();
position = in.readInt();
services = in.readHashMap(null);
banners = in.readHashMap(null);
portsOpen = in.readArrayList(Integer.class.getClassLoader());
portsClosed = in.readArrayList(Integer.class.getClassLoader());
}
#SuppressWarnings("unchecked")
public static final Creator CREATOR = new Creator() {
public HostBean createFromParcel(Parcel in) {
return new HostBean(in);
}
public HostBean[] newArray(int size) {
return new HostBean[size];
}
};
}
This is my simple adapter class:
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.SimpleViewHolder> {
private final Context mContext;
private ArrayList<HostBean> mData;
final HostBean host = new HostBean();
public void add(HostBean s,int position) {
position = position == -1 ? getItemCount() : position;
host.hostsection=s;
mData.add(position,s); //at this line of code i'm getting error
notifyItemInserted(position);
}
public void remove(int position){
if (position < getItemCount() ) {
mData.remove(position);
notifyItemRemoved(position);
}
}
public static class SimpleViewHolder extends RecyclerView.ViewHolder {
public final TextView mac;
public final TextView vendor;
public final TextView ip;
public SimpleViewHolder(View view) {
super(view);
ip = (TextView) view.findViewById(R.id.ip);
mac = (TextView) view.findViewById(R.id.mac);
vendor = (TextView) view.findViewById(R.id.vendor);
}
}
public SimpleAdapter(Context context, List<HostBean> data) {
mContext = context;
if (data != null)
mData = new ArrayList<HostBean>();
}
public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.list_host, parent, false);
return new SimpleViewHolder(view);
}
#Override
public void onBindViewHolder(SimpleViewHolder holder, final int position) {
holder.ip.setText( (CharSequence) mData.get(position) );
holder.mac.setText( "" );
holder.vendor.setText( "" );
}
#Override
public int getItemCount() {
return mData.size();
}
}
This is my simple sectioned recyclerview adapter class:
public class SimpleSectionedRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context mContext;
private static final int SECTION_TYPE = 0;
private boolean mValid = true;
private int mSectionResourceId;
private int mTextResourceId;
private LayoutInflater mLayoutInflater;
private RecyclerView.Adapter mBaseAdapter;
private SparseArray<Section> mSections = new SparseArray<Section>();
public SimpleSectionedRecyclerViewAdapter(Context context, int sectionResourceId, int textResourceId,
RecyclerView.Adapter baseAdapter) {
mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mSectionResourceId = sectionResourceId;
mTextResourceId = textResourceId;
mBaseAdapter = baseAdapter;
mContext = context;
mBaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onChanged() {
mValid = mBaseAdapter.getItemCount()>0;
notifyDataSetChanged();
}
#Override
public void onItemRangeChanged(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeChanged(positionStart, itemCount);
}
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeInserted(positionStart, itemCount);
}
#Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeRemoved(positionStart, itemCount);
}
});
}
public static class SectionViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public SectionViewHolder(View view, int mTextResourceid) {
super(view);
title = (TextView) view.findViewById(mTextResourceid);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int typeView) {
if (typeView == SECTION_TYPE) {
final View view = LayoutInflater.from(mContext).inflate(mSectionResourceId, parent, false);
return new SectionViewHolder(view,mTextResourceId);
}else{
return mBaseAdapter.onCreateViewHolder(parent, typeView -1);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder sectionViewHolder, int position) {
if (isSectionHeaderPosition(position)) {
((SectionViewHolder)sectionViewHolder).title.setText(mSections.get(position).title);
}else{
mBaseAdapter.onBindViewHolder(sectionViewHolder,sectionedPositionToPosition(position));
}
}
#Override
public int getItemViewType(int position) {
return isSectionHeaderPosition(position)
? SECTION_TYPE
: mBaseAdapter.getItemViewType(sectionedPositionToPosition(position)) +1 ;
}
public static class Section {
int firstPosition;
int sectionedPosition;
CharSequence title;
public Section(int firstPosition, CharSequence title) {
this.firstPosition = firstPosition;
this.title = title;
}
public CharSequence getTitle() {
return title;
}
}
public void setSections(Section[] sections) {
mSections.clear();
Arrays.sort(sections, new Comparator<Section>() {
#Override
public int compare(Section o, Section o1) {
return (o.firstPosition == o1.firstPosition)
? 0
: ((o.firstPosition < o1.firstPosition) ? -1 : 1);
}
});
int offset = 0; // offset positions for the headers we're adding
for (Section section : sections) {
section.sectionedPosition = section.firstPosition + offset;
mSections.append(section.sectionedPosition, section);
++offset;
}
notifyDataSetChanged();
}
public int positionToSectionedPosition(int position) {
int offset = 0;
for (int i = 0; i < mSections.size(); i++) {
if (mSections.valueAt(i).firstPosition > position) {
break;
}
++offset;
}
return position + offset;
}
public int sectionedPositionToPosition(int sectionedPosition) {
if (isSectionHeaderPosition(sectionedPosition)) {
return RecyclerView.NO_POSITION;
}
int offset = 0;
for (int i = 0; i < mSections.size(); i++) {
if (mSections.valueAt(i).sectionedPosition > sectionedPosition) {
break;
}
--offset;
}
return sectionedPosition + offset;
}
public boolean isSectionHeaderPosition(int position) {
return mSections.get(position) != null;
}
#Override
public long getItemId(int position) {
return isSectionHeaderPosition(position)
? Integer.MAX_VALUE - mSections.indexOfKey(position)
: mBaseAdapter.getItemId(sectionedPositionToPosition(position));
}
#Override
public int getItemCount() {
return (mValid ? mBaseAdapter.getItemCount() + mSections.size() : 0);
}
}
This is how is initialize the arraylist:
hosts = new ArrayList<HostBean>();
This is my activity code for setting adapter to recyclerview:
RecyclerView list =findViewById(R.id.output);
list.setHasFixedSize( true );
list.setLayoutManager( new LinearLayoutManager( this ) );
list.addItemDecoration(new DividerItemDecoration(this,LinearLayoutManager.VERTICAL));
SimpleAdapter mAdapter = new SimpleAdapter(this,hosts);
List<SimpleSectionedRecyclerViewAdapter.Section> sections =
new ArrayList<SimpleSectionedRecyclerViewAdapter.Section>();
//Sections
sections.add(new SimpleSectionedRecyclerViewAdapter.Section(0,"Know Devices"));
sections.add(new SimpleSectionedRecyclerViewAdapter.Section(5,"Unknown Devices"));
SimpleSectionedRecyclerViewAdapter.Section[] dummy = new SimpleSectionedRecyclerViewAdapter.Section[sections.size()];
SimpleSectionedRecyclerViewAdapter mSectionedAdapter = new
SimpleSectionedRecyclerViewAdapter(this,R.layout.section,R.id.section_text,mAdapter);
mSectionedAdapter.setSections(sections.toArray(dummy));
list.setAdapter( mSectionedAdapter );
Your mData is an ArrayList<>. Therefore you can not pass key, value for that. You can only pass one param, either key or value. List is not a map.
private ArrayList<HostBean> mData;
mData.add(position,s); // Can not do this
If you want a key value relationship, then use HashMap like this.
private HashMap<Integer, HostBean> mData;
I need to implement parcelable in my custom class "ArtistInfo"
with the following structure:
public class ArtistInfo implements Parcelable {
private String artist;
// album name to list of ids of songs
private HashMap> albumInfo;
// song id to songInfo
private SparseArray songsMap;
protected ArtistInfo(Parcel in) {
artist = in.readString();
}
public static final Creator CREATOR = new Creator() {
#Override
public ArtistInfo createFromParcel(Parcel in) {
return new ArtistInfo(in);
}
#Override
public ArtistInfo[] newArray(int size) {
return new ArtistInfo[size];
}
};
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public void addSongsInfoToAlbum(List songsInfo, String album) {
if (albumInfo == null) {
albumInfo = new HashMap();
}
if (songsMap == null) {
songsMap = new SparseArray();
}
List songsIds = new ArrayList();
for (SongInfo songInfo : songsInfo) {
songsIds.add(songInfo.getId());
songsMap.put(songInfo.getId(), songInfo);
}
List songsIdsForAlbum = getSongIdsForAlbum(album);
songsIdsForAlbum.addAll(songsIds);
albumInfo.put(album, songsIdsForAlbum);
}
private List getSongIdsForAlbum(String album) {
if (albumInfo == null) {
return new ArrayList();
}
List songsIds = albumInfo.get(album);
return songsIds == null ? new ArrayList() : songsIds;
}
public HashMap> getAlbumInfo() {
return albumInfo;
}
public SparseArray getSongsMap() {
if (songsMap == null) {
songsMap = new SparseArray();
}
return songsMap;
}
#Override
public String toString() {
return "ArtistInfo{" +
"artist='" + artist + '\'' +
", albumInfo=" + albumInfo.toString() +
", songsMap=" + songsMap.toString() +
'}';
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(artist);
}
}
And following is the structure of the "SongInfo" class used in the above class:
public class SongInfo implements Parcelable {
private Integer id;
private String name;
private String url;
public SongInfo(Integer id, String name, String url) {
this.id = id;
this.name = name;
this.url = url;
}
protected SongInfo(Parcel in) {
if (in.readByte() == 0) {
id = null;
} else {
id = in.readInt();
}
name = in.readString();
url = in.readString();
}
public static final Creator CREATOR = new Creator() {
#Override
public SongInfo createFromParcel(Parcel in) {
return new SongInfo(in);
}
#Override
public SongInfo[] newArray(int size) {
return new SongInfo[size];
}
};
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 String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
if (id == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeInt(id);
}
dest.writeString(name);
dest.writeString(url);
}
}
Now as you can see there is no problem in implementing the Parcelable interface in the SongInfo class, but I am not able to understand how to read and write the albumInfo and songsMap variables in the Constructor and writeToParcel method respectively. Can someone please help me understand how should I go ahead with that. Thanks!
The idea is iterate through each item in albumInfo and songsMap then add it into Parcelable.
Write to parcel.
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(artist);
// Write album info
dest.writeInt(albumInfo.size());
for (Map.Entry<String, List<Integer>> item : albumInfo.entrySet()) {
dest.writeString(item.getKey());
dest.writeList(item.getValue());
}
// Write song map
dest.writeInt(songsMap.size());
for (int i = 0; i < songsMap.size(); i++) {
int key = songsMap.keyAt(i);
dest.writeInt(key);
dest.writeParcelable(songsMap.get(key), flags);
}
}
Read from parcel
protected ArtistInfo(Parcel in) {
artist = in.readString();
// Read album info
albumInfo = new HashMap<>();
int albumInfoSize = in.readInt();
for (int i = 0; i < albumInfoSize; i++) {
String key = in.readString();
List<Integer> value = new ArrayList<>();
in.readList(value, null);
albumInfo.put(key, value);
}
// Read song map
songsMap = new SparseArray<>();
int songsMapSize = in.readInt();
for (int i = 0; i < songsMapSize; i++) {
int key = in.readInt();
SongInfo value = in.readParcelable(SongInfo.class.getClassLoader());
songsMap.put(key, value);
}
}
I am crafting a non profit charity app. Despite I have checked many questions in stack and google, i could not solve the problem.
I have 3 classes:
- BaseCell implements Parcelable (Base class)
- Needy extends BaseCell
- UserBasket class which hold the list of all classes extend BaseCell
Problem
I am holding Needy classes with Arraylist in UserBasket class. When i send it to another activity, if i add 1 item to the UserBasket i am getting ridiculous result(Missing or wrong characters) and if i add more than 1 item then i am getting exception.
I need to deliver UserBasket class(list of needy items) to the payment activity so i can calculate the total price for charity and perform necessary actions.
public abstract class BaseCell implements Parcelable {
String imageUrl;
int percentageOfCollectedDonation;
String needyTitle;
String needyDescription;
protected String category;
protected int amountOfCollectedDonation=0;
protected int amountOfTargetDonation=0;
protected int amountOfDonater=0;
protected int drawableID;
protected String campaignCode;
protected int maxInstallmentNumber;
int price;
public String getCellType() {
return cellType;
}
protected String cellType ;
/**
* How many of this campaign purchased by user
* */
protected int userPurchaseAmount = 1;
protected BaseCell(String cellType)
{
this.cellType = cellType;
}
protected BaseCell(Parcel in)
{
drawableID = in.readInt();
price = in.readInt();
imageUrl = in.readString();
needyTitle = in.readString();
needyDescription = in.readString();
category = in.readString();
campaignCode = in.readString();
maxInstallmentNumber = in.readInt();
userPurchaseAmount = in.readInt();
}
public static final Parcelable.Creator<BaseCell> CREATOR = new Parcelable.Creator<BaseCell>() {
#Override
public BaseCell createFromParcel(Parcel in) {
String cellType = in.readString();
BaseCell baseCell = null;
if (cellType.equals("Needy"))
{
baseCell = (Needy)new Needy(in);
}else
if (cellType.equals("Qurban"))
{
baseCell = (Qurban)new Qurban(in);
}
return baseCell;
}
#Override
public BaseCell[] newArray(int size) {
return new BaseCell[size];
}
};
public void writeToParcel(Parcel out, int flags) {
out.writeString(getCellType());
}
public BaseCell(String imageUrl, int drawableID, String needyTitle, String needyDescription, int amountOfCollectedDonation, int amountOfTargetDonation, int amountOfDonater, String category,String campaignCode, int maxInstallmentNumber, int price)
{
this.imageUrl = imageUrl;
this.drawableID = drawableID;
this.needyTitle = needyTitle;
this.needyDescription = needyDescription;
this.amountOfCollectedDonation = amountOfCollectedDonation;
this.amountOfTargetDonation = amountOfTargetDonation;
this.amountOfDonater = amountOfDonater;
this.category = category;
this.campaignCode = campaignCode;
this.maxInstallmentNumber = maxInstallmentNumber;
this.price= price;
}
}
Needy
public class Needy extends BaseCell {
protected Needy(Parcel in) {
super(in);
cellType ="Needy";
}
public static final Parcelable.Creator<Needy> CREATOR = new Parcelable.Creator<Needy>() {
#Override
public Needy createFromParcel(Parcel in) {
return new Needy(in);
}
#Override
public Needy[] newArray(int size) {
return new Needy[size];
}
};
public Needy(String imageUrl, int drawableID, String needyTitle, String needyDescription, int amountOfCollectedDonation, int amountOfTargetDonation, int amountOfDonater, String category, String campaignCode, int maxInstallmentNumber, int price) {
super(imageUrl, drawableID, needyTitle, needyDescription, amountOfCollectedDonation, amountOfTargetDonation, amountOfDonater, category, campaignCode, maxInstallmentNumber,price);
cellType = "Needy";
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getCellType());
super.writeToParcel(dest,flags);
dest.writeInt(drawableID);
dest.writeInt(price);
dest.writeString(imageUrl);
dest.writeString(needyTitle);
dest.writeString(needyDescription);
dest.writeString(category);
dest.writeString(campaignCode);
dest.writeInt(maxInstallmentNumber);
dest.writeInt(userPurchaseAmount);
}
#Override
public void setUserPurchaseAmount(int userPurchaseAmount) {
super.setUserPurchaseAmount(userPurchaseAmount);
}
}
UserBasket
public class UserBasket implements Parcelable{
List<BaseCell> userBasket;
/**
* holds all items to be purchased
* */
public UserBasket(List<BaseCell> userBasket) {
this.userBasket = userBasket;
}
public UserBasket() {
userBasket = new ArrayList<>();
}
protected UserBasket(Parcel in) {
super();
setUserBasket(new ArrayList<BaseCell>());
userBasket = in.createTypedArrayList(BaseCell.CREATOR);
//in.readTypedList(userBasket,BaseCell.CREATOR);
}
public static final Parcelable.Creator<UserBasket> CREATOR = new Parcelable.Creator<UserBasket>() {
#Override
public UserBasket createFromParcel(Parcel in) {
return new UserBasket(in);
}
#Override
public UserBasket[] newArray(int size) {
return new UserBasket[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(userBasket);
}
public List<BaseCell> getUserBasket() {
return userBasket;
}
public void setUserBasket(List<BaseCell> userBasket) {
this.userBasket = userBasket;
}
/**
* Add to the basket list
* */
public void add(Needy donation) {
if (donation != null)
userBasket.add(donation);
}
/**
* Remove from basket list
* */
public void remove(int position)
{
if (userBasket.size()>0)
userBasket.remove(position);
}
}
sending userBasket arrayList with items from MainActivity
Navigate.navigateToPaymentPayuStart
(MainActivity.this,userBasket,"basket");
// userBasket arrayList with "basket" key
Receiving UserBasket in paymentPayu activity
UserBasket userBasket = getIntent().getParcelableExtra("basket");
How am i going to get UserBasket properly in paymentPayuActivity.
I appreciate for the help
Thank you.
It does seem like you are handling the Parcelable implementation wrong. e.i. you are reading some of the variables from the Parcel twice, which isn't allowed. So to improve this, we'll try to make your code a bit simpler. As Needy doesn't actually have any variables, it seems better to let BaseCell handle all of the parcelable implementation, i've tried to create a mock for you, so depending on the rest of your code it might need a bit of tweaking.
First i've removed all of the Parcelable implementation in Needy and is just pointing it's CREATOR to BaseCell.
public class Needy extends BaseCell {
protected Needy(Parcel in) {
super(in);
cellType ="Needy";
}
// Since Needy doesn't actually store any variables, we don't need a Creator for it.
// Just point it to BaseCell.CREATOR and let it handle it
public static final Parcelable.Creator<BaseCell> CREATOR = BaseCell.CREATOR;
public Needy(String imageUrl, int drawableID, String needyTitle, String needyDescription, int amountOfCollectedDonation, int amountOfTargetDonation, int amountOfDonater, String category, String campaignCode, int maxInstallmentNumber, int price) {
super(imageUrl, drawableID, needyTitle, needyDescription, amountOfCollectedDonation, amountOfTargetDonation, amountOfDonater, category, campaignCode, maxInstallmentNumber,price);
cellType = "Needy";
}
}
And then we'll let BaseCell handle all of the Parcelable implementation, like so:
public abstract class BaseCell implements Parcelable {
/**
* ALL OF YOUR VARIABLES, GETTERS, SETTERS AND CONSTRUCTORS GOES HERE
*/
#Override
public int describeContents() {
return 0;
}
public static final Parcelable.Creator<BaseCell> CREATOR = new Parcelable.Creator<BaseCell>() {
#Override
public BaseCell createFromParcel(Parcel in) {
String cellType = in.readString();
if (cellType.equals("Needy")) {
return (Needy)new Needy(in);
} else if (cellType.equals("Qurban")) {
return (Qurban)new Qurban(in);
}
return null;
}
#Override
public BaseCell[] newArray(int size) {
return new BaseCell[size];
}
};
protected BaseCell(Parcel in) {
drawableID = in.readInt();
price = in.readInt();
imageUrl = in.readString();
needyTitle = in.readString();
needyDescription = in.readString();
category = in.readString();
campaignCode = in.readString();
maxInstallmentNumber = in.readInt();
userPurchaseAmount = in.readInt();
}
public void writeToParcel(Parcel out, int flags) {
// cellType written first, and read by Creator
out.writeString(cellType);
// the rest is read by the BaseCell constructor
out.writeInt(drawableID);
out.writeInt(price);
out.writeString(imageUrl);
out.writeString(needyTitle);
out.writeString(needyDescription);
out.writeString(category);
out.writeString(campaignCode);
out.writeInt(maxInstallmentNumber);
out.writeInt(userPurchaseAmount);
}
}
Now, I have three class, the base class is BaseWidget which implements Parcelable, two subclasses are SelectWidget and TextWidget. Then, I use a class named WidgetInfo (also implements Parcelable) to keep a list of BaseWidget or SelectWidget or TextWidget objects.
While I put WidgetInfo object into an Intent to start TestActivity, and I received WidgetInfo in TestActivity ,but all the elements of list (which in WidgetInfo) convert to BaseWidget object. And subclass object member variable is lost. What is problem???
BaseWidget.java:
public class BaseWidget implements Parcelable{
private String name;
public BaseWidget() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected BaseWidget(Parcel in) {
this.name = in.readString();
}
public static final Creator<BaseWidget> CREATOR = new Creator<BaseWidget>() {
#Override
public BaseWidget createFromParcel(Parcel in) {
return new BaseWidget(in);
}
#Override
public BaseWidget[] newArray(int size) {
return new BaseWidget[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
}
}
TextWidget.java:
public class TextWidget extends BaseWidget{
private String width = "100";
public TextWidget() {
}
public String getWidth() {
return width;
}
public void setWidth(String width) {
this.width = width;
}
protected TextWidget(Parcel in) {
super(in);
width = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(width);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<TextWidget> CREATOR = new Creator<TextWidget>() {
#Override
public TextWidget createFromParcel(Parcel in) {
return new TextWidget(in);
}
#Override
public TextWidget[] newArray(int size) {
return new TextWidget[size];
}
};
}
SelectWidget.java:
public class SelectWidget extends BaseWidget{
private int height = 200;
public SelectWidget() {
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
protected SelectWidget(Parcel in) {
super(in);
height = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(height);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<SelectWidget> CREATOR = new Creator<SelectWidget>() {
#Override
public SelectWidget createFromParcel(Parcel in) {
return new SelectWidget(in);
}
#Override
public SelectWidget[] newArray(int size) {
return new SelectWidget[size];
}
};
}
WidgetInfo.java:
public class WidgetInfo implements Parcelable{
private List<BaseWidget> widgetList;
public WidgetInfo() {
}
public List<BaseWidget> getWidgetList() {
return widgetList;
}
public void setWidgetList(List<BaseWidget> widgetList) {
this.widgetList = widgetList;
}
protected WidgetInfo(Parcel in) {
widgetList = in.createTypedArrayList(BaseWidget.CREATOR);
}
public static final Creator<WidgetInfo> CREATOR = new Creator<WidgetInfo>() {
#Override
public WidgetInfo createFromParcel(Parcel in) {
return new WidgetInfo(in);
}
#Override
public WidgetInfo[] newArray(int size) {
return new WidgetInfo[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(widgetList);
}
}
start Intent:
WidgetInfo info = new WidgetInfo();
BaseWidget widget1 = new BaseWidget();
BaseWidget widget2 = new TextWidget();
BaseWidget widget3 = new SelectWidget();
List<BaseWidget> list = new ArrayList<>();
list.add(widget1);
list.add(widget2);
list.add(widget3);
info.setWidgetList(list);
Intent intent = new Intent(this, TestActivity.class);
intent.putExtra("widgetInfo", info);
startActivity(intent);
I'm trying to pass a custom parceable class which contains an array of another custom parceable class between activities. I tried to follow the advice here, but it didn't work for me.
This is the inner class, it works fine when passed alone:
import android.os.Parcel;
import android.os.Parcelable;
public class EntryImage implements Parcelable {
public int imageId;
public int entryid_id;
public String url;
public int height;
public EntryImage(int imageId, int entryid_id, String url, int height) {
this.imageId = imageId;
this.entryid_id = entryid_id;
this.url = url;
this.height = height;
}
public EntryImage(Parcel in) {
readFromParcel(in);
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(imageId);
parcel.writeInt(entryid_id);
parcel.writeString(url);
parcel.writeInt(height);
}
private void readFromParcel(Parcel in) {
imageId = in.readInt();
entryid_id = in.readInt();
url = in.readString();
height = in.readInt();
}
public static final Parcelable.Creator<EntryImage> CREATOR = new Parcelable.Creator<EntryImage>() {
public EntryImage createFromParcel(Parcel in) {
return new EntryImage(in);
}
public EntryImage[] newArray(int size) {
return new EntryImage[size];
}
};
}
And this is the outer class. The problem is in the last few lines of readFrom and writeToParcel:
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Arrays;
public class Entry implements Parcelable {
public int entryId;
public String name;
public EntryImage[] images;
public Entry(int entryId, String name, EntryImage[] images) {
this.entryId = entryId;
this.name = name;
this.images = images;
}
public Entry(Parcel in) {
readFromParcel(in);
}
public EntryImage getEntryImage (int asdf) {
return images[asdf];
}
#Override
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(entryId);
parcel.writeString(name);
parcel.writeParcelableArray(images, flags);
}
private void readFromParcel(Parcel in) {
entryId = in.readInt();
name = in.readString();
//images = in.readTypedArray(EntryImage[].class.getClassLoader());
Parcelable[] parcelableArray = in.readParcelableArray(EntryImage.class.getClassLoader());
EntryImage[] images = null;
if (parcelableArray != null) {
images = Arrays.copyOf(parcelableArray, parcelableArray.length, EntryImage[].class);
}
}
public static final Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator<Entry>() {
public Entry createFromParcel(Parcel in) {
return new Entry(in);
}
public Entry[] newArray(int size) {
return new Entry[size];
}
};
}
The line in Entry.readFromParcel
EntryImage[] images = null;
should instead be
images = null;