writing multiple objects to parcel - java

I am trying to save an enum 'Status' into a custom class that implements parcelable. I have found online how I can save Strings, ints or enums in one class that implements parcelable, but not how I can save these three things all at once. I am sorry if the solution is obvious, but I just can't figure it out.
Here is what my enum looks like:
public enum Status {
INITIALIZED, UPDATED, DELETED
}
And this is what I have so far:
public class Recipe implements Parcelable{
private String id;//this should be an int, same problem
private String recipeName;
private String recipePreperation;
private Status status;
private final static int MAX_PREVIEW = 50;
public Recipe(int parId, String parRecipeName, String parRecipePreperation) {
this.id = "" + parId;
this.recipeName = parRecipeName;
this.recipePreperation = parRecipePreperation;
this.status = Status.INITIALIZED;
}
public Recipe(Parcel in){
String[] data = new String[4];
in.readStringArray(data);
this.id = data [0];
this.recipeName = data[1];
this.recipePreperation = data[2];
this.status = data[3];//what I intend to do, I know this is wrong
}
public int GetId() {
return Integer.parseInt(id);
}
public String GetRecipeName() {
return this.recipeName;
}
public void SetRecipeName(String parRecipeName) {
this.recipeName = parRecipeName;
}
public String GetRecipePreperation() {
return this.recipePreperation;
}
public void SetRecipePreperation(String parRecipePreperation) {
this.recipePreperation = parRecipePreperation;
}
public Status GetStatus() {
return this.status;
}
public void SetStatus(Status parStatus) {
this.status = parStatus;
}
public String toString() {
String recipe = this.recipeName + "\n" + this.recipePreperation;
String returnString;
int maxLength = MAX_PREVIEW;
if (recipe.length() > maxLength) {
returnString = recipe.substring(0, maxLength - 3) + "...";
} else {
returnString = recipe;
}
return returnString;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int arg1) {
dest.writeStringArray(new String [] {
this.id,
this.recipeName,
this.recipePreperation,
this.status//what I intend to do, I know this is wrong
});
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Recipe createFromParcel(Parcel in) {
return new Recipe(in);
}
public Recipe[] newArray(int size) {
return new Recipe[size];
}
};
}
How do I save an int, an array of strings and an enum into a class that implements the parcelable, so it can writeToParcel()?

There's no need to read and write to/from string array. Just write each string and finally the status as Serializable. This is how I fix it.
public Recipe(Parcel in){
this.id = in.readString();
this.recipeName = in.readString();
this.recipePreperation = in.readString();
this.status = (Status) in.readSerializable();
}
public void writeToParcel(Parcel dest, int arg1) {
dest.writeString(this.id);
dest.writeString(this.recipeName);
dest.writeString(this.recipePreperation);
dest.writeSerializable(this.status);
}

Related

Superclass overriding Subclass with default values from constructor in Java

I have an assignment and my superclass default values always override the values I pass in the Test main method. In the debugger, i see the passing of the productNumber(1234) and productTitle("Daughter"), but then it's overridden with the default values. Any thoughts, i keep making minor changes, checking for changes, still the same results.
Product Superclass
public abstract class Product {
private int productNumber;
private String productTitle;
//Two constructors required
public Product(){
productNumber = 0;
productTitle = "";
}
public Product(int productNumber, String productTitle) {
this.productNumber = productNumber;
this.productTitle = productTitle;
}
public void setProductNumber(int productNumber) {
this.productNumber = productNumber;
}
public int getProductNumber() {
return productNumber;
}
public void setProductTitle(String productTitle) {
this.productTitle = productTitle;
}
public String getProductTitle() {
return productTitle;
}
//Override toString() required
#Override
public String toString() {
return productNumber + " " + productTitle;
}
// Required Product class declares abstract method with this signature: public String getDisplayText()
public abstract String getDisplayText();
//Override equals() required
#Override
public boolean equals(Object object) {
if (object instanceof Product) {
Product product2 = (Product) object;
if (productNumber == (product2.getProductNumber()) &&
productTitle.equals(product2.getProductTitle())){
return true;
}
}
return false;
}
}
Music Subclass extends Product Superclass
public class Music extends Product {
private String artist;
private String style;
private String medium;
public Music() {
super();
artist = "";
style = "";
medium = "";
}
public Music(int productNumber, String productTitle, String artist, String style, String medium) {
super();
this.artist = artist;
this.style = style;
this.medium = medium;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public String getStyle() {
return style;
}
public void setStyle(String style) {
this.style = style;
}
public String getMedium() {
return medium;
}
public void setMedium(String medium) {
this.medium = medium;
}
#Override
public String getDisplayText() {
return super.toString() + " by " + artist + " " + style + " " + medium;
}
#Override
public boolean equals(Object object){
if (object instanceof Music){
Music m = (Music) object;
if (artist.equals(m.getArtist()) &&
style.equals(m.getStyle()) &&
medium.equals(m.getMedium())){
return true;
}
}
return false;
}
}
Print String
public class Test {
public static void main(String[] args) {
// Expected result: 1234 Daughter by Pearljam Alternative online
Music music1 = new Music(1234,"Daughter", "Pearljam","Alternative","online");
System.out.println(music1.getDisplayText());
}
}
you are not passing values from subclass to your parentclass
instead of super() you need to do below -
super(productNumber,productTitle);
update needed in your code :-
public Music(int productNumber, String productTitle, String artist, String style, String medium) {
super(productNumber,productTitle);
this.artist = artist;
this.style = style;
this.medium = medium;
}
You need to pass productNumber and productTitle in the super(..., ...) call inside the Music constructor up to the parent class.
You need to invoke
super(productNumber, productTitle)
inside the Music constructor to pass the parameters to its parent.

Custom TiledDataSource with paging library

I tried to implement custom TiledDataSource for using with paging library. When I used LivePagedListProvider like returns type for my Dao method it worked fine (after table items updating - ui updated automatically).
#Query("SELECT * FROM " + Table.States.PLAY_STATE + ", "+Table.Chart.ARTIST+ " ORDER BY position ASC")
LivePagedListProvider<Artist> loadArtists();
But when I try implement custom TiledDataSource for LivePagerListProvider table updates not triggered my observers.
Abstract generic class:
public abstract class PagedNetworkBoundResource<ResultType, RequestType> extends TiledDataSource<ResultType> {
#Override
public int countItems() {
return DataSource.COUNT_UNDEFINED;
}
#Override
public List<ResultType> loadRange(int startPosition, int count) {
fetchFromNetwork(startPosition, count);
return loadFromDb(startPosition, count);
}
#WorkerThread
private void fetchFromNetwork(int startPosition, int count) {
if (createCall(startPosition, count) != null)
try {
Response<RequestType> response = createCall(startPosition, count).execute();
if (response.isSuccessful() && response.code() == 200) {
saveCallResult(response.body());
}
} catch (IOException e) {
e.printStackTrace();
}
}
#WorkerThread
protected abstract void saveCallResult(#NonNull RequestType item);
#WorkerThread
protected abstract List<ResultType> loadFromDb(int startPosition, int count);
#WorkerThread
protected abstract Call<RequestType> createCall(int startPosition, int count);
public LiveData<PagedList<ResultType>> getAsLiveData() {
return new LivePagedListProvider<Integer, ResultType>() {
#Override
protected DataSource<Integer, ResultType> createDataSource() {
return PagedNetworkBoundResource.this;
}
}.create(0, new PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPageSize(20)
.setInitialLoadSizeHint(20)
.build());
}
}
My dao method for this case:
#Query("SELECT * FROM " + Table.States.PLAY_STATE + ", "+Table.Chart.ARTIST+ " ORDER BY position ASC LIMIT (:limit) OFFSET (:offset)")
List<Artist> loadArtists(int offset, int limit);
I update Table.States.PLAY_STATE.
public void updatePlayerState(PlayerStateEntity state){
new Thread(() -> {
dao.deleteState();
dao.insertState(state);
}).run();
}
#Dao
public interface PlayStateDao {
#Insert(onConflict = OnConflictStrategy.REPLACE)
void insertState(PlayerStateEntity playEntity);
#Query("DELETE FROM " + Table.States.PLAY_STATE)
void deleteState();
#Query("SELECT * FROM "+Table.States.PLAY_STATE)
PlayerStateEntity getPlayerState();
}
#Entity(tableName = Table.States.PLAY_STATE)
public class PlayerStateEntity extends IdEntity {
#ColumnInfo(name = "album_played_id")
private Long albumPlayedId = -1L;
#ColumnInfo(name = "track_played_id")
private Long trackPlayedId = -1L;
#ColumnInfo(name = "artist_played_id")
private Long artistPlayedId = -1L;
#ColumnInfo(name = "state")
private PlayingState state;
#ColumnInfo(name = "playing_type")
private PlayingType playingType;
public Long getAlbumPlayedId() {
return albumPlayedId;
}
public void setAlbumPlayedId(Long albumPlayedId) {
this.albumPlayedId = albumPlayedId;
}
public Long getTrackPlayedId() {
return trackPlayedId;
}
public void setTrackPlayedId(Long trackPlayedId) {
this.trackPlayedId = trackPlayedId;
}
public Long getArtistPlayedId() {
return artistPlayedId;
}
public void setArtistPlayedId(Long artistPlayedId) {
this.artistPlayedId = artistPlayedId;
}
public PlayingState getState() {
return state;
}
public void setState(PlayingState state) {
this.state = state;
}
public PlayingType getPlayingType() {
return playingType;
}
public void setPlayingType(PlayingType playingType) {
this.playingType = playingType;
}
}
class Artist extends PlayEntity{
private String name;
private String link;
private String picture;
#ColumnInfo(name = "picture_small")
private String pictureSmall;
#ColumnInfo(name = "picture_medium")
private String pictureMedium;
#ColumnInfo(name = "picture_big")
private String pictureBig;
#ColumnInfo(name = "picture_xl")
private String pictureXl;
private Boolean radio;
private String tracklist;
private Integer position;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
public String getPictureSmall() {
return pictureSmall;
}
public void setPictureSmall(String pictureSmall) {
this.pictureSmall = pictureSmall;
}
public String getPictureMedium() {
return pictureMedium;
}
public void setPictureMedium(String pictureMedium) {
this.pictureMedium = pictureMedium;
}
public String getPictureBig() {
return pictureBig;
}
public void setPictureBig(String pictureBig) {
this.pictureBig = pictureBig;
}
public String getPictureXl() {
return pictureXl;
}
public void setPictureXl(String pictureXl) {
this.pictureXl = pictureXl;
}
public Boolean getRadio() {
return radio;
}
public void setRadio(Boolean radio) {
this.radio = radio;
}
public String getTracklist() {
return tracklist;
}
public void setTracklist(String tracklist) {
this.tracklist = tracklist;
}
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
#Override
public boolean isItemPlaying() {
return getId() == getArtistPlayedId().longValue() && getPlayingType() == PlayingType.Artist && getState() == PlayingState.Playing;
}
}
public abstract class PlayEntity extends PlayerStateEntity {
public abstract boolean isItemPlaying();
}
public class ArtistsRepository {
private final ChartArtistDao chartArtistDao;
private final DeezerService deezerService;
#Inject
public ArtistsRepository(ChartArtistDao chartArtistDao, DeezerService deezerService) {
this.chartArtistDao = chartArtistDao;
this.deezerService = deezerService;
}
public LiveData<PagedList<ChartArtistDao.Artist>> getArtist() {
return new PagedNetworkBoundResource<ChartArtistDao.Artist, ModelList<ChartArtistEntity>>() {
#Override
protected void saveCallResult(#NonNull ModelList<ChartArtistEntity> item) {
if (item != null) {
chartArtistDao.saveArtists(item.getItems());
}
}
#Override
protected List<ChartArtistDao.Artist> loadFromDb(int startPosition, int count) {
return chartArtistDao.loadArtists(startPosition, count);
}
#Override
protected Call<ModelList<ChartArtistEntity>> createCall(int startPosition, int count) {
return deezerService.getChartArtist(startPosition, count);
}
}.getAsLiveData();
}
}
For each Artist items I add fields from PlayerStateEntity (not good solution but this easy way to represent state of ui items). After PlayerStateEntity table updates Room should notify about data changes, but doesn't do it.
I understand that Room doesn't know about query what I used, and can't updates my RecyclerView which provide by paging library. But maybe some one knows how to notify Room about tables which I used inside mine DataSource for future triggering ui updates?
The problem was related with custom DataSource realization. When data has changed, LivePagedListProvider should create a new DataSource instance for right ui updating. I used the same instance, so my previous solution is not right.

Java serialization, android

I need to save data into object
Here is my object class where I must store data:
public static class FilterEntity implements Serializable {
public int ageFrom;
public int ageTo;
public String sex;
public String status;
public void setAgeFrom()
{
this.ageFrom = ageFrom;
}
public void setAgeTo()
{
this.ageTo = ageTo;
}
public void setSex()
{
this.sex = sex;
}
public void setStatus()
{
this.status = status;
}
public Integer getAgeFrom()
{
return ageFrom;
}
public Integer getAgeTo()
{
return ageTo;
}
public String getSex()
{
return sex;
}
public String getStatus()
{
return status;
}
}
Is it correct implementation of serialization?
In the main activity I'm saving data to FilterEntity object
private FilterEntity filter = new FilterEntity();
filter.status = valueOf(spStatusForSearch.toString());
filter.sex = valueOf(rgSex);
filter.ageTo = sbAgeHigh.getProgress();
filter.ageFrom = sbAgeLow.getProgress();
Can I do it such way?
How I can get access to data, from the third class?
don't use static
public class FilterEntity implements Serializable {
public int ageFrom;
public int ageTo;
public String sex;
public String status;
public void setAgeFrom()
{
this.ageFrom = ageFrom;
}
public void setAgeTo()
{
this.ageTo = ageTo;
}
public void setSex()
{
this.sex = sex;
}
public void setStatus()
{
this.status = status;
}
public Integer getAgeFrom()
{
return ageFrom;
}
public Integer getAgeTo()
{
return ageTo;
}
public String getSex()
{
return sex;
}
public String getStatus()
{
return status;
}
}
To set Values to Model Class
FilterEntity filter = new FilterEntity();
filter.setStatus(spStatusForSearch.toString());
filter.setSex(rgSex);
filter.setAgeTo(sbAgeHigh.getProgress());
filter.setAgeFrom(sbAgeLow.getProgress());
And to get Values
String status = filter.getStatus();
String sex = filter.getSex();
String ageTo = filter.getAgeTo();
String ageFrom = filter.getAgeFrom();
public class FilterEntity
{
public int ageFrom;
public int ageTo;
public String sex;
public String status;
public FilterEntity(int ageFrom, int ageTo, String sex,String status)
{
this.ageFrom = ageFrom;
this.ageTo = ageTo;
this.sex = sex;
this.status = status;
}
public int getAgeFrom()
{
return ageFrom;
}
public int getAgeTo()
{
return ageTo;
}
public String getSex()
{
return sex;
}
public String getStatus()
{
return status;
}
}
// in your main activity file where your are saving the data
static ArrayList<FilterEntity> data=new ArrayList<FilterEntity>();
data.add(new FilterEntity(sbAgeLow.getProgress(),sbAgeHigh.getProgress(),valueOf(rgSex),valueOf(spStatusForSearch.toString())));
// you can add multiple like this
/*Now pass this arraylist to your third activity through intent or make this arraylist static so will be able to access this arraylist anywhere through the name of the class example: MainActivity.data*/
//Now in the third activity where you want the data of the object , get the arraylist
ArrayList data=MainActivity.data;
Iterator iterotor=data.iterator();
while (iterotor.hasNext())
{
FilterEntity filterEntity=iterotor.next();
// the multiple values you add
String status = filterEntity.getStatus();
String sex = filterEntity.getSex();
int ageTo = filterEntity.getAgeTo();
int ageFrom = filterEntity.getAgeFrom();
}

ClassCastException while assigning values to bundle

I am getting error while loading the bundle. I have checked all the initialization and casting but not able to resolve this.
Please see the reference:
Bundle bundle = getIntent().getExtras();
if (bundle.containsKey("MEASUREMENT_DATA")) {
body_scaleMeasurement = bundle.getParcelable("MEASUREMENT_DATA");
evaluate_info();
}
The code for body _scaleMeasurement
package model;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.SerializedName;
public class BodyScaleMeasurement implements Parcelable {
#SerializedName("id")
private String id;
#SerializedName("client_platform_version")
private String client_platform_version;
#SerializedName("client_build_number")
#SerializedName("client_platform_data")
private Client_platform_data client_platform_data;
#SerializedName("ble_device_data")
private Ble_device_data ble_device_data;
private transient boolean is_synchronized;
public BodyScaleMeasurement() {
}
public BodyScaleMeasurement(String id, String client_platform_version, int client_build_number, Client_platform_data client_platform_data, Ble_device_data ble_device_data, boolean is_synchronized) {
this.id = id;
this.client_platform_version = client_platform_version;
this.client_build_number = client_build_number;
this.client_platform_data = client_platform_data;
this.ble_device_data = ble_device_data;
this.is_synchronized = is_synchronized;
}
public boolean is_synchronized() {
return is_synchronized;
}
public void setIs_synchronized(boolean is_synchronized) {
this.is_synchronized = is_synchronized;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClient_platform_version() {
return client_platform_version;
}
public void setClient_platform_version(String client_platform_version) {
this.client_platform_version = client_platform_version;
}
public int getClient_build_number() {
return client_build_number;
}
public void setClient_build_number(int client_build_number) {
this.client_build_number = client_build_number;
}
public Client_platform_data getClient_platform_data() {
return client_platform_data;
}
public void setClient_platform_data(Client_platform_data client_platform_data) {
this.client_platform_data = client_platform_data;
}
public Ble_device_data getBle_device_data() {
return ble_device_data;
}
public void setBle_device_data(Ble_device_data ble_device_data) {
this.ble_device_data = ble_device_data;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.client_platform_version);
dest.writeInt(this.client_build_number);
dest.writeParcelable(this.client_platform_data, 0);
dest.writeParcelable(this.ble_device_data, 0);
dest.writeByte(is_synchronized ? (byte) 1 : (byte) 0);
}
protected BodyScaleMeasurement(Parcel in) {
this.id = in.readString();
this.client_platform_version = in.readString();
this.client_build_number = in.readInt();
this.client_platform_data = in.readParcelable(Client_platform_data.class.getClassLoader());
this.ble_device_data = in.readParcelable(Ble_device_data.class.getClassLoader());
this.is_synchronized = in.readByte() != 0;
}
public static final Parcelable.Creator<BodyScaleMeasurement> CREATOR = new Parcelable.Creator<BodyScaleMeasurement>() {
public BodyScaleMeasurement createFromParcel(Parcel source) {
return new BodyScaleMeasurement(source);
}
public BodyScaleMeasurement[] newArray(int size) {
return new BodyScaleMeasurement[size];
}
};
}
This is the error which i get. Please refer the image I have attached.
It was happening because I changed the type of other variables from double to int. It was not expected though, but I am myself not understaning it. I reverted the changes in which the conversion was done.
Also, there was change in values too after conversion. For example : if i was sending 50 to bundle with a key. It was being setted as some negative integer.
Is it possible that the Client_platform_data implements Parcelable and has
Parcelable.Creator<Ble_device_data> ?

Android: getParcelable returning null?

As a follow on from my last question: Passing Arraylist between activities? Using Parcelable
I'm now attempting to pass my ArrayList via Parcelable. However, when it's gotten from the other activity it returns null. I can't seem to figure out why. I've got the following...
ResultsList.java
public class ResultsList extends ArrayList<SearchList> implements Parcelable {
/**
*
*/
private static final long serialVersionUID = -78190146280643L;
public ResultsList(){
}
public ResultsList(Parcel in){
readFromParcel(in);
}
#SuppressWarnings({ "rawtypes" })
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public ResultsList createFromParcel(Parcel in) {
return new ResultsList(in);
}
public Object[] newArray(int arg0) {
return null;
}
};
private void readFromParcel(Parcel in) {
this.clear();
//First we have to read the list size
int size = in.readInt();
//Reading remember that we wrote first the Name and later the Phone Number.
//Order is fundamental
for (int i = 0; i < size; i++) {
String title = in.readString();
String Des = in.readString();
String message = in.readString();
SearchList c = new SearchList(title,Des,link);
this.add(c);
}
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
int size = this.size();
//We have to write the list size, we need him recreating the list
dest.writeInt(size);
//We decided arbitrarily to write first the Name and later the Phone Number.
for (int i = 0; i < size; i++) {
SearchList c = this.get(i);
dest.writeString(c.gettitle());
dest.writeString(c.getDescription());
dest.writeString(c.getmessage());
}
}
}
SearchList.java
public class SearchList {
private String title;
private String description;
private String message;
public SearchList(String name, String phone, String mail) {
super();
this.title = name;
this.description = phone;
this.message = mail;
}
public String gettitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getmessage() {
return message;
}
public void setmessage(String link) {
this.message = message;
}
}
listOfResults is declared as ResultsList listOfResults = new ResultsList(); and filled earlier in the code It's then sent with...
Intent intent = new Intent(this ,newthing.class);
Bundle b = new Bundle();
b.putParcelable("results", listOfResults);
startActivityForResult(intent,0);
Receiving...
Bundle extras = getIntent().getExtras();
ResultsList results = extras.getParcelable("results");
I'd like to point out I'm testing this null thing by checking the size() of the Arraylist going into the Bundle and then it coming out. It goes in fine and comes out null.
Didn't attach bundle to intent! (doh!) was pointed out by a kind gent on IRC! #android-dev

Categories

Resources