How can I pass List<Model> from Activity to Fragment - java

I wanna pass List from Activity to Fragment. But I don't know model class have to implements 'Parcelable' or 'Serializable'. Also How to define implements methods. Thank you for seeing this question. Under codes are my Model class.
public class Artist {
private String artistName;
private String aritstImgPath;
private List<Album> albumList;
public Artist() {
}
public Artist(String artistName, String aritstImgPath, List<Album> albumList) {
this.artistName = artistName;
this.aritstImgPath = aritstImgPath;
this.albumList = albumList;
}
public String getArtistName() {
return artistName;
}
public void setArtistName(String artistName) {
this.artistName = artistName;
}
public String getAritstImgPath() {
return aritstImgPath;
}
public void setAritstImgPath(String aritstImgPath) {
this.aritstImgPath = aritstImgPath;
}
public List<Album> getAlbumList() {
return albumList;
}
public void setAlbumList(List<Album> albumList) {
this.albumList = albumList;
}
#Override
public String toString() {
return "Artist{" +
"artistName='" + artistName + '\'' +
", aritstImgPath='" + aritstImgPath + '\'' +
", albumList=" + albumList +
'}';
}
}
public class Album {
private String albumTitle;
private String albumImgPath;
private List<Song> songList;
public Album() {
}
public Album(String albumTitle, String albumImgPath, List<Song> songList) {
this.albumTitle = albumTitle;
this.albumImgPath = albumImgPath;
this.songList = songList;
}
public String getAlbumTitle() {
return albumTitle;
}
public void setAlbumTitle(String albumTitle) {
this.albumTitle = albumTitle;
}
public String getAlbumImgPath() {
return albumImgPath;
}
public void setAlbumImgPath(String albumImgPath) {
this.albumImgPath = albumImgPath;
}
public List<Song> getSongList() {
return songList;
}
public void setSongList(List<Song> songList) {
this.songList = songList;
}
#Override
public String toString() {
return "Album{" +
"albumTitle='" + albumTitle + '\'' +
", albumImgPath='" + albumImgPath + '\'' +
", songList=" + songList +
'}';
}
}
public class Song {
private String songTitle;
private String playTime;
private String assPath;
private String ampPath;
public Song() {
}
public Song(String songTitle, String playTime, String assPath, String ampPath) {
this.songTitle = songTitle;
this.playTime = playTime;
this.assPath = assPath;
this.ampPath = ampPath;
}
public String getSongTitle() {
return songTitle;
}
public void setSongTitle(String songTitle) {
this.songTitle = songTitle;
}
public String getPlayTime() {
return playTime;
}
public void setPlayTime(String playTime) {
this.playTime = playTime;
}
public String getAssPath() {
return assPath;
}
public void setAssPath(String assPath) {
this.assPath = assPath;
}
public String getAmpPath() {
return ampPath;
}
public void setAmpPath(String ampPath) {
this.ampPath = ampPath;
}
#Override
public String toString() {
return "Song{" +
"songTitle='" + songTitle + '\'' +
", playTime='" + playTime + '\'' +
", assPath='" + assPath + '\'' +
", ampPath='" + ampPath + '\'' +
'}';
}
}
Will I have to implements parcel able or serializable in all my Model class?
When I make bundle What is a correct method? (putSerializable? putParcelable? )
How can I get List in fragment.

You can implement parcelable in your model class.
public class ModelClass implements Parcelable {
public ModelClass(Parcel in) {
super();
readFromParcel(in);
}
public static final Parcelable.Creator<ModelClass> CREATOR = new Parcelable.Creator<ModelClass>() {
public ModelClass createFromParcel(Parcel in) {
return new ModelClass (in);
}
public ModelClass [] newArray(int size) {
return new ModelClass [size];
}
};
public void readFromParcel(Parcel in) {
Value1 = in.readInt();
Value2 = in.readInt();
Value3 = in.readInt();
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(Value1);
dest.writeInt(Value2);
dest.writeInt(Value3);
}
}
Sending object to fragment.
ArrayList<ModelClass> arraylist = new Arraylist<>();
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("arraylist", arraylist);
Receiving object from fragment
Bundle extras = getIntent().getExtras();
ArrayList<ModelClass> arraylist = extras.getParcelableArrayList("arraylist");
ModelClass model= arrayList[0];

Thers is two way to pass your List from Activity to Fragment.
1.Serializable and 2. Parcelable
Will I have to implements parcel able or serializable in all my Model class? --> Yes you have to implements Parcelable or serializable in all your classes
When I make bundle What is a correct method? (putSerializable? putParcelable?) --> If yor are using serializable then you have to use putSerializable otherwise putParcelable
How can I get List in fragment. -->
1. Using Serializable
Sending List of object
Bundle bundle = new Bundle();
bundle.putSerializable("key",arraylist);
Receiving list of object
List<Model> = (List<Model>) getArguments().getSerializable("key);
2. Using Parcelable
Sending List of object
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("key", arraylist);
Receiving list of object
List<Model> arraylist = getArguments().getParcelableArrayList("arraylist");

Related

how to send arraylist to another activity through parcable

I have a model class which implement Parcelable and 2 string and one arraylist of another model class
i can retrive title1 and title2 but i am not able to retrive option4 arraylist its get null
`public class TopListSubListModel implements Parcelable {
String title1,title2;
ArrayList option4;
public TopListSubListModel(String title1, String title2, ArrayList<Option4Model> option4) {
this.title1 = title1;
this.title2 = title2;
this.option4 = option4;
}
protected TopListSubListModel(Parcel in) {
title1 = in.readString();
title2 = in.readString();
}
public static final Creator<TopListSubListModel> CREATOR = new Creator<TopListSubListModel>() {
#Override
public TopListSubListModel createFromParcel(Parcel in) {
return new TopListSubListModel(in);
}
#Override
public TopListSubListModel[] newArray(int size) {
return new TopListSubListModel[size];
}
};
public String getTitle1() {
return title1;
}
public void setTitle1(String title1) {
this.title1 = title1;
}
public String getTitle2() {
return title2;
}
public void setTitle2(String title2) {
this.title2 = title2;
}
public ArrayList<Option4Model> getOption4() {
return option4;
}
public void setOption4(ArrayList<Option4Model> option4) {
this.option4 = option4;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(title1);
parcel.writeString(title2);
}
}`

What is the error which causes the app to stop when retrieving data from Firebase?

This is an app that uses the Firebase database.
I have added all the data in firebase and now I need to retrieve it and display using listview.
I tried to fetch and show the data in my app from firebase but the app is stopping every time.
Take a look at the screenshot
This is the Country model class
Country.java
public class Country {
private String name;
private String total;
private String newCases;
private String totalDeaths;
private String newDeaths;
private String totalRecovered;
private String activeCases;
private String seriousCases;
public Country() {
}
public Country(String name, String total, String newCases, String totalDeaths, String newDeaths, String totalRecovered, String activeCases, String seriousCases) {
this.name = name;
this.total = total;
this.newCases = newCases;
this.totalDeaths = totalDeaths;
this.newDeaths = newDeaths;
this.totalRecovered = totalRecovered;
this.activeCases = activeCases;
this.seriousCases = seriousCases;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTotal() {
return total;
}
public void setTotal(String total) {
this.total = total;
}
public String getNewCases() {
return newCases;
}
public void setNewCases(String newCases) {
this.newCases = newCases;
}
public String getTotalDeaths() {
return totalDeaths;
}
public void setTotalDeaths(String totalDeaths) {
this.totalDeaths = totalDeaths;
}
public String getNewDeaths() {
return newDeaths;
}
public void setNewDeaths(String newDeaths) {
this.newDeaths = newDeaths;
}
public String getTotalRecovered() {
return totalRecovered;
}
public void setTotalRecovered(String totalRecovered) {
this.totalRecovered = totalRecovered;
}
public String getActiveCases() {
return activeCases;
}
public void setActiveCases(String activeCases) {
this.activeCases = activeCases;
}
public String getSeriousCases() {
return seriousCases;
}
public void setSeriousCases(String seriousCases) {
this.seriousCases = seriousCases;
}
}
This is the Activity class
Country_List.java
public class Country_List extends AppCompatActivity {
ListView listView;
FirebaseDatabase firebaseDatabase;
DatabaseReference reff;
ArrayList<String> countries;
ArrayAdapter<String> adapter;
Country country;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_country__list);
listView = (ListView) findViewById(R.id.listView);
country = new Country();
firebaseDatabase = FirebaseDatabase.getInstance();
reff = firebaseDatabase.getReference().child("country");
countries = new ArrayList<>();
adapter = new ArrayAdapter<>(Country_List.this, R.layout.country_info, R.id.country_info_list, countries);
reff.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnapshot.getChildren()){
country = ds.getValue(Country.class);
countries.add("Country Name:" + country.getName().toString() + "\n" + "Total Cases:" + country.getTotal().toString() + "\n" + "New Cases:" + country.getNewCases().toString() + "\n" + "Total Deaths:" + country.getTotalDeaths().toString() + "\n" + "New Deaths:" + country.getNewCases().toString() + "Total Recovered:" + country.getTotalRecovered().toString() + "Active Cases:" + country.getActiveCases().toString() + "\n" + "Serious Cases:" + country.getSeriousCases().toString());
}
listView.setAdapter(adapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
StackTrace
com.google.firebase.database.DatabaseException: Failed to convert value of type java.lang.Long to String
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertString(com.google.firebase:firebase-database##19.2.1:425)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database##19.2.1:216)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToType(com.google.firebase:firebase-database##19.2.1:178)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.access$100(com.google.firebase:firebase-database##19.2.1:47)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(com.google.firebase:firebase-database##19.2.1:592)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper$BeanMapper.deserialize(com.google.firebase:firebase-database##19.2.1:562)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertBean(com.google.firebase:firebase-database##19.2.1:432)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.deserializeToClass(com.google.firebase:firebase-database##19.2.1:231)
at com.google.firebase.database.core.utilities.encoding.CustomClassMapper.convertToCustomClass(com.google.firebase:firebase-database##19.2.1:79)
at com.google.firebase.database.DataSnapshot.getValue(com.google.firebase:firebase-database##19.2.1:203)
at com.example.covid_19explorer.Country_List$1.onDataChange(Country_List.java:40)
at com.google.firebase.database.core.ValueEventRegistration.fireEvent(com.google.firebase:firebase-database##19.2.1:75)
at com.google.firebase.database.core.view.DataEvent.fire(com.google.firebase:firebase-database##19.2.1:63)
at com.google.firebase.database.core.view.EventRaiser$1.run(com.google.firebase:firebase-database##19.2.1:55)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
To solve this, you please change all the properties in your Country class to be of type long, except the name, which should remain a String. Please also change all the setters and getters. Your class should look like this:
public class Country {
private String name;
private long total, newCases, totalDeaths, newDeaths, totalRecovered, activeCases, seriousCases;
public Country() {}
public Country(String name, long total, long newCases, long totalDeaths, long newDeaths, long totalRecovered, long activeCases, long seriousCases) {
this.name = name;
this.total = total;
this.newCases = newCases;
this.totalDeaths = totalDeaths;
this.newDeaths = newDeaths;
this.totalRecovered = totalRecovered;
this.activeCases = activeCases;
this.seriousCases = seriousCases;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
public long getNewCases() {
return newCases;
}
public void setNewCases(long newCases) {
this.newCases = newCases;
}
public long getTotalDeaths() {
return totalDeaths;
}
public void setTotalDeaths(long totalDeaths) {
this.totalDeaths = totalDeaths;
}
public long getNewDeaths() {
return newDeaths;
}
public void setNewDeaths(long newDeaths) {
this.newDeaths = newDeaths;
}
public long getTotalRecovered() {
return totalRecovered;
}
public void setTotalRecovered(long totalRecovered) {
this.totalRecovered = totalRecovered;
}
public long getActiveCases() {
return activeCases;
}
public void setActiveCases(long activeCases) {
this.activeCases = activeCases;
}
public long getSeriousCases() {
return seriousCases;
}
public void setSeriousCases(long seriousCases) {
this.seriousCases = seriousCases;
}
}
There is one more thing that you need to do, which is to change the type for the newCases property in the database this time, to be of type long, as it is a String now. That plus sign (+) is not recommended to be added in the database, you should add it programmatically.

How do I implement polymorphism properly with Interface?

I have 2 model classes(Data,Title) which contain the same field:
String dataID. I want to get both of this IDs with interface implementation.
I am passing Title model through Bundle to another Activity, passing Data model through Bundle in that same activity(just creating new instance of the activity and resetting information).
I want both of my model classes to implement SharedID interface, with method String getSharedId();
How can I get different ids but from different models? I need to put only one parameter and it should be String in my ViewModelFactory constructor.
public class Data implements SharedId,Parcelable {
private String text;
private String textHeader;
private int viewType;
private String mainId;
private String dataID;
public Data() { }
public String getDataID() {
return dataID;
}
public void setDataID(String dataID) {
this.dataID = dataID;
}
public String getText() {return (String) trimTrailingWhitespace(text); }
public void setText(String text) {
this.text = (String) trimTrailingWhitespace(text);
}
public String getTextHeader() {
return (String) trimTrailingWhitespace(textHeader);
}
public void setTextHeader(String textHeader) {
this.textHeader = textHeader;
}
public int getViewType() {
return viewType;
}
public void setViewType(int viewType) {
this.viewType = viewType;
}
public String getMainId() {
return mainId;
}
public void setMainId(String mainId) {
this.mainId = mainId;
}
protected Data(Parcel in) {
text = in.readString();
textHeader = in.readString();
viewType = in.readInt();
mainId = in.readString();
dataID = in.readString();
}
#Override
public String toString() {
return "Data{" +
"order=" +
", text='" + text + '\'' +
", textHeader='" + textHeader + '\'' +
", viewType=" + viewType +
'}';
}
#SuppressWarnings("StatementWithEmptyBody")
public static CharSequence trimTrailingWhitespace(CharSequence source) {
if (source == null) {
return "";
}
int i = source.length();
// loop back to the first non-whitespace character
while (--i >= 0 && Character.isWhitespace(source.charAt(i))) {
}
return source.subSequence(0, i + 1);
}
public static final Creator<Data> CREATOR = new Creator<Data>() {
#Override
public Data createFromParcel(Parcel in) {
return new Data(in);
}
#Override
public Data[] newArray(int size) {
return new Data[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(text);
dest.writeString(textHeader);
dest.writeInt(viewType);
dest.writeString(mainId);
dest.writeString(dataID);
}
#Override
public String getSharedDataId() {
return getDataID();
}
}
public class Title implements SharedId,Parcelable {
private String dataID;
private String title;
public Title() { }
protected Title(Parcel in) {
dataID = in.readString();
title = in.readString();
}
public String getDataID() {
return dataID;
}
public void setDataID(String dataID) {
this.dataID = dataID;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public static final Creator<Title> CREATOR = new Creator<Title>() {
#Override
public Title createFromParcel(Parcel in) {
return new Title(in);
}
#Override
public Title[] newArray(int size) {
return new Title[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(dataID);
dest.writeString(title);
}
#NonNull
#Override
public String toString() {
return "Title{" +
"dataID='" + dataID + '\'' +
", titleOrder=" +
", title='" + title + '\'' +
'}';
}
#Override
public String getSharedDataId() {
return getDataID();
}
}
And My DetailActivity code, I already succeeded with the mission of passing id, but i need to do this trough interfaces :( So help me out friends, would really appreciate it!
public class DetailActivity extends AppCompatActivity implements
DetailAdapter.OnDialogClickListener,
DetailAdapter.OnDetailClickListener {
private static String id;
private String parentId;
private Data data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
TextView tvToolbarTitle = findViewById(R.id.title_toolbar_detail);
tvToolbarTitle.setSelected(true);
findViewById(R.id.btn_back).setOnClickListener(v -> finish());
ArrayList<SharedId> sharedIds = new ArrayList<>();
sharedIds.add(new Title());
sharedIds.add(new Data());
for (SharedId sharedId : sharedIds){
System.out.println(sharedId.getSharedDataId());
}
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
Title model = bundle.containsKey("ID") ? bundle.getParcelable("ID") : null;
Data childModel = bundle.containsKey("idDetail") ? bundle.getParcelable("idDetail") : null;
}
if (bundle != null) {
Title model = bundle.containsKey("ID") ? bundle.getParcelable("ID") : null;
Data childModel = bundle.containsKey("idDetail") ? bundle.getParcelable("idDetail") : null;
String parentId = bundle.getString("mainScreenId");
if (parentId != null) {
this.parentId = parentId;
}
if (model != null) {
this.id = model.getDataID();
tvToolbarTitle.setText(model.getTitle());
}
if (childModel != null) {
this.id = childModel.getDataID();
tvToolbarTitle.setText(childModel.getTextHeader());
}
}
RecyclerView recyclerView = findViewById(R.id.rv_detail);
DetailAdapter adapter = new DetailAdapter(this, this);
recyclerView.setAdapter(adapter);
// TODO: 3/1/19 change it to single ID // DetailViewModelFactory(); // id != null ? id : parentId
DetailViewModelFactory detailViewModelFactory = new DetailViewModelFactory(id != null ? id : parentId);
DetailActivityViewModel viewModel = ViewModelProviders.of(this, detailViewModelFactory).get(DetailActivityViewModel.class);
FirebaseListLiveData<Data> liveData = viewModel.getLiveDataQuery();
liveData.observe(this, adapter::setNewData);
}
#Override
public void onDialogClicked(#NonNull String text) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(HtmlCompat.fromHtml(text, 0, null, new HandlerHtml()));
builder.setPositiveButton("Ok", null);
builder.show();
}
#Override
public void onDetailClicked(Data data) {
Intent intent = new Intent();
DetailActivity.open(DetailActivity.this);
intent.putExtra("idDetail", data);
intent.putExtra("mainScreenId", id);
startActivity(intent);
}
public static void open(#NonNull Context context) {
context.startActivity(new Intent(context, InfoActivity.class));
}
}
I found a bit different, but working solution!
I create an interface
public interface SharedId {
String getSharedDataId();
String getHeader();
}
Both of my model classes Data + Title implemented Interface and methods from it.
In DetailActivity i created 2 Strings.
private String mainId;
private String detailId;
And then passed ids with my model classes with bundle
`SharedId mainId = new Title();
SharedId detailId = new Data();
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
mainId = bundle.containsKey("ID") ? bundle.getParcelable("ID") : null;
detailId = bundle.containsKey("idDetail") ?
bundle.getParcelable("idDetail") : null;
}
if (mainId != null) {
this.detailId = mainId.getSharedDataId();
tvToolbarTitle.setText(mainId.getHeader());
}
if (detailId != null) {
this.mainId = detailId.getSharedDataId();
tvToolbarTitle.setText(detailId.getHeader());
}
And passed in my ViewmodelFactory
DetailViewModelFactory detailViewModelFactory =
new DetailViewModelFactory(this.detailId != null ?
this.detailId : this.mainId);

How to implement parcelable with my custom class containing Hashmap and SparseArray?

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 send an parcelable class from Android ActivityForResult and receive null

Sorry for common question, but I check all and can't find error. I send class from Activity and receive NULL. Checking after creating Intent is correct (readbackCi in my code). Could you please help me find solution?
My class CityItem
import android.os.Parcel;
import android.os.Parcelable;
public class CityItem implements Parcelable {
public static final String ITEM_SEP = System.getProperty("line.separator");
public static final String NAME = "City";
public static final String REGNAME = "Region";
public static final String CODE = "Code";
public static final String SEARCH = "Search";
private String mName;
private String mRegName;
private String mSearch;
private String mCode;
public CityItem(String name, String regname, String code, String search) {
mName = name;
mRegName = regname;
mSearch = search;
mCode = code;
}
private CityItem(Parcel in) {
in.readParcelable(CityItem.class.getClassLoader());
setName(in.readString());
setRegName(in.readString());
setCode(in.readString());
setSearch(in.readString());
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public String getRegName() {
return mRegName;
}
public void setRegName(String regname) {
mRegName = regname;
}
public String getCode() {
return mCode;
}
public void setCode(String code) {
mRegName = code;
}
public String getSearch() {
return mSearch;
}
public void setSearch(String search) {
mRegName = search;
}
public String toString() {
return mName + ITEM_SEP + mRegName + ITEM_SEP + mCode + ITEM_SEP
+ mSearch;
}
public String toLog() {
return "Name:" + mName + ITEM_SEP + "Region:" + mRegName
+ ITEM_SEP + "Code:" + mCode + ITEM_SEP + "Search:"
+ mSearch + "\n";
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] { mName, mRegName, mCode, mSearch });
}
public static final Parcelable.Creator<CityItem> CREATOR = new Parcelable.Creator<CityItem>() {
#Override
public CityItem createFromParcel(Parcel source) {
return new CityItem(source);
}
#Override
public CityItem[] newArray(int size) {
return new CityItem[size];
}
};
}
Second activity
public void enterClicked(CityItem str) {
Log.i(TAG,"Entered enterClicked()");
Intent result = new Intent();
result.putExtra("TAG", str);
CityItem readbackCi = result.getParcelableExtra("TAG");
Log.d(TAG, "\n\n\t" + readbackCi.NAME);
setResult(this.RESULT_OK, result);
finish();
}
Main activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i(TAG, "Entered onActivityResult()");
if(ADD_DERIVAL_REQUEST == requestCode && this.RESULT_OK == resultCode)
{
CityItem ci = (CityItem) getIntent().getParcelableExtra("TAG");
if (null != ci) {
EditText1.setText(ci.getName());
}
return;
} else if (ADD_DERIVAL_REQUEST == requestCode && RESULT_CANCELED == resultCode)
{
return;
}
}
You need to use Intent data to get result back.
CityItem ci = (CityItem) data.getParcelableExtra("TAG");
getIntent() will return intent that was used for main activity start and it is not the one you are interested in.
The implementation for your parcelable class CityItem is not correct. Check this:
package com.mobgen.halo.android.sdk.generalcontent.business.parser;
import android.os.Parcel;
import android.os.Parcelable;
public class CityItem implements Parcelable {
public static final String ITEM_SEP = System.getProperty("line.separator");
public static final String NAME = "City";
public static final String REGNAME = "Region";
public static final String CODE = "Code";
public static final String SEARCH = "Search";
private String mName;
private String mRegName;
private String mSearch;
private String mCode;
public CityItem(String name, String regname, String code, String search) {
mName = name;
mRegName = regname;
mSearch = search;
mCode = code;
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public String getRegName() {
return mRegName;
}
public void setRegName(String regname) {
mRegName = regname;
}
public String getCode() {
return mCode;
}
public void setCode(String code) {
mRegName = code;
}
public String getSearch() {
return mSearch;
}
public void setSearch(String search) {
mRegName = search;
}
public String toString() {
return mName + ITEM_SEP + mRegName + ITEM_SEP + mCode + ITEM_SEP + mSearch;
}
public String toLog() {
return "Name:" + mName + ITEM_SEP + "Region:" + mRegName
+ ITEM_SEP + "Code:" + mCode + ITEM_SEP + "Search:"
+ mSearch + "\n";
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.mName);
dest.writeString(this.mRegName);
dest.writeString(this.mSearch);
dest.writeString(this.mCode);
}
protected CityItem(Parcel in) {
this.mName = in.readString();
this.mRegName = in.readString();
this.mSearch = in.readString();
this.mCode = in.readString();
}
public static final Creator<CityItem> CREATOR = new Creator<CityItem>() {
public CityItem createFromParcel(Parcel source) {
return new CityItem(source);
}
public CityItem[] newArray(int size) {
return new CityItem[size];
}
};
}
Beside that, you have to use the "data" Intent instead of the one from getIntent() which is the one that was used to start this activity.

Categories