To newcomers reading this, skip down to the part where I stop trying to use the SharedPreferences. It could have worked but apparently Gson started throwing security exceptions so I needed to start using intents. I'm still clueless.
I'm trying to save an arraylist of objects into a SharedPreferences file, by storing all of the object variables in the file. Here is some of the code exhibiting that.
SharedPreferences.Editor editor = getSharedPreferences(prefName, MODE_PRIVATE).edit();
editor.putInt("lorBucks", lorandBucks[0]);
editor.commit();
//But wait there's more!
SharedPreferences.Editor editor2 = getSharedPreferences("BoughtStuff", MODE_PRIVATE).edit();
System.out.println("IS THIS THE CULPRIT: BOUGHTITEMS SIZE: " + boughtItems.size());
editor2.putInt("Items Amount", boughtItems.size());
editor2.apply();
for(int i = 0; i<boughtItems.size(); i++) {
editor2.putString(Integer.toString(i) + " name", boughtItems.get(i).name);
editor2.putInt(Integer.toString(i) + " price", boughtItems.get(i).price);
editor2.putString(Integer.toString(i) + " image", boughtItems.get(i).imageName);
}
editor2.commit();
}
Now, this code obviously leaves out a lot of the action, but the important part is how it is saving values into the file. In a for(i) loop, it goes through an array of objects to save their variables under different identifiers.
Some of this code looks messy I know, but that's because of all of the debugging I've been doing trying to sort this problem out.
Now, here is an example of how I try to call these values:
//Loading and Creating Bought Items
SharedPreferences sps = getSharedPreferences("BoughtStuff", MODE_PRIVATE);
for(int i = 0; i<sps.getInt("Items Amount", 0); i++){
System.out.println("Items Amount: " + sps.getInt("Items Amount", 0));
boughtItems.add(new StoreItem(sps.getInt(Integer.toString(i) + " price", -1), sps.getString(Integer.toString(i) + " name", " "), sps.getString(Integer.toString(i) + " image", " "), layout, this));
System.out.println(sps.getString("0 name", "DAMNIT!!"));
System.out.println(boughtItems.get(i).name);
System.out.println("NUMBER OF BOUGHT ITEMS: " + boughtItems.size());
}
So I'm pretty screwed here, because somewhere along the way all of those values got lost (I've tried to display the object using toString()). But this is the soft blow, the entire app manages to crash at a later portion, when I'm actually calling these values into action. Here:
#Override
public void onResume(){
super.onResume();
showItems();
}
The showItems method:
public void showItems(){
for(int i = 0; i<boughtItems.size(); i++){
boughtItems.get(i).setUpShop();
//final StoreItem[] stores = new StoreItem[1];
// stores[0] = boughtItems.get(i);
// final int[] c = new int[1];
// boughtItems.get(i).getIb().setOnClickListener(new View.OnClickListener(){
// #Override
// public void onClick(View v){
// c[0] = 1;
// }
// });
// if(c[0] == 1){
// boughtItems.remove(i);
// }
}
}
And last but not least, the StoreItem.setUpShop() method, which works perfectly fine as long as it gets a good image file, but since the data isn't flowing properly it crashes the whole app. Here it is:
public void setUpShop() {
ib.setImageResource(getResourceID(imageName, "drawable", act.getApplicationContext()));
ib.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1200));
ib.setScaleType(ImageView.ScaleType.CENTER_CROP);
TextView shopLabel = new TextView(act);
shopLabel.setText(name + ": " + price + " Love Bucks");
shopLabel.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
shopLabel.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 100));
layout.addView(shopLabel);
layout.addView(ib);
}
Now, I assume I'm just being very stupid with how I'm storing the data here (I'm an extreme beginner at coding apps and data persistence in general) so please let me know what I can do to make this work and what I should use in the future. I've tried my best to explain the whole situation but if there are any questions I would be happy to answer them.
So, I changed my approach and I now have a class here:
package com.example.lorand.saimibutton;
import android.os.Parcel;
import android.os.Parcelable;
public class StoreArrayHolder implements Parcelable {
String price = "";
String name = "";
String image = "";
protected StoreArrayHolder(Parcel in) {
price = in.readString();
name = in.readString();
image = in.readString();
}
public static final Creator<StoreArrayHolder> CREATOR = new Creator<StoreArrayHolder>() {
#Override
public StoreArrayHolder createFromParcel(Parcel in) {
return new StoreArrayHolder(in);
}
#Override
public StoreArrayHolder[] newArray(int size) {
return new StoreArrayHolder[size];
}
};
public StoreArrayHolder(){
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(price);
dest.writeString(name);
dest.writeString(image);
}
}
I use this to store the variables my objects need passed.
This is how I try to use the array between classes. I put this code in the onStop and onPause methods.
private void sendIntent() {
ArrayList<StoreArrayHolder> aList = new ArrayList<>();
for (int i = 0; i < boughtItems.size(); i++) {
StoreArrayHolder temp = new StoreArrayHolder();
temp.setPrice(Integer.toString(boughtItems.get(i).price));
temp.setName(boughtItems.get(i).name);
temp.setImage(boughtItems.get(i).imageName);
aList.add(temp);
}
Intent i = new Intent(this, PouchActivity.class);
i.putExtra("list", aList);
startActivity(i);
}
This is retrieving the array, I put this code in the onStart method.
private void getArrayList() {
if (getIntent().getExtras() != null) {
if (getIntent().hasExtra("list")) {
itemsInfo = getIntent().getParcelableExtra("list");
System.out.println("FUCK YEAH IT WORKED!!!! " + itemsInfo.get(1).getName());
}
}
}
Now I get a nullpointer error meaning that none of the data got transferred, even though the list intent was technically sent!
Initialize shared preference
SharedPreferences prefs = context.getSharedPreferences(PREF_NAME,PRIVATE_MODE);
SharedPreferences.Editor editor;
Method to store array list in to preference (Here i use Gson to convert object in to json)
public void setListToPreferance(String key, ArrayList<OBJECT_OF_MODELCLASS> list) {
Gson gson = new Gson();
String json = gson.toJson(list);
editor = prefs.edit();
editor.putString(key, json);
editor.apply();
}
Method to get list from preference (It will returns the ArrayList)
so you can directly get list from this method
public ArrayList<OBJECT_OF_MODELCLASS> getListProductModel(String key) {
Gson gson = new Gson();
Type type = new TypeToken<ArrayList<OBJECT_OF_MODELCLASS>>() {
}.getType();
ArrayList<OBJECT_OF_MODELCLASS> list = gson.fromJson(prefs.getString(key, ""), type);
if (list == null) {
list = new ArrayList<OBJECT_OF_MODELCLASS>();
}
return list;
}
Pass ArrayListfrom one activity to another activity using Intent
1.Create a Model of array list with Parcelable implemantation
public class DemoModel implements Parcelable{
String price = "";
String totla_amount = "";
protected DemoModel(Parcel in) {
price = in.readString();
totla_amount = in.readString();
}
public static final Creator<DemoModel> CREATOR = new Creator<DemoModel>() {
#Override
public DemoModel createFromParcel(Parcel in) {
return new DemoModel(in);
}
#Override
public DemoModel[] newArray(int size) {
return new DemoModel[size];
}
};
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getTotla_amount() {
return totla_amount;
}
public void setTotla_amount(String totla_amount) {
this.totla_amount = totla_amount;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(price);
dest.writeString(totla_amount);
}
}
Inside the From activity from where you want to send data
private void sendIntent() {
ArrayList<DemoModel> list = new ArrayList<>();
//Add data in to this list or use your list which you want to send
Intent intent = new Intent(this, ConatctsModelActivity.class);
intent.putExtra("list", list);
startActivity(intent);
}
Retrieve array list in To second activity.
ArrayList<DemoModel> list_in_second_activity = new ArrayList<>();
private void getArrayLis() {
if (getIntent().getExtras() != null) {
if (getIntent().hasExtra("list")) {
list_in_second_activity =
getIntent().getParcelableExtra("list");
}
}
}
Related
I'm trying to put a Parcelable object as an extra in an intent and pass it to the next Activity, and it doesn't crash but the object changes dramatically. I'm sending when clicking on an item from a RecyclerView in a Fragment and opening an Activity from it.
This is how I send it:
AdminProfile adminProfile = list.get(position).admin;
Intent intent = new Intent(view.getContext(),ClosedChatActivity.class);
intent.putExtra("chat",adminProfile);
view.getContext().startActivity(intent);
This how I get it:
adminProfile = (AdminProfile) getIntent().getExtras().getParcelable("chat");
And here the class:
public class AdminProfile implements Parcelable {
public static final Creator<AdminProfile> CREATOR = new Creator<AdminProfile>() {
#Override
public AdminProfile createFromParcel(Parcel in) {
return new AdminProfile(in);
}
#Override
public AdminProfile[] newArray(int size) {
return new AdminProfile[size];
}
};
public Long idUser;
public String name;
public String professio;
public String description;
public List<WebLink> webLinks;
public Long idOficina;
protected AdminProfile(Parcel in) {
if (in.readByte() == 0) {
idUser = null;
} else {
idUser = in.readLong();
}
name = in.readString();
professio = in.readString();
description = in.readString();
webLinks = in.createTypedArrayList(WebLink.CREATOR);
if (in.readByte() == 0) {
idOficina = null;
} else {
idOficina = in.readLong();
}
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeLong(idUser);
parcel.writeString(name);
parcel.writeString(professio);
parcel.writeString(description);
parcel.writeLong(idOficina);
parcel.writeList(webLinks);
}
}
I can't understand why, but when I send the object I have UserId=3, but when I get it it's userId=55834574848. Any ideas?
The Parcelable functions were filled automatically by Android Studio, and reading the first byte messed it up.
Changing
if (in.readByte() == 0) {
idUser = null;
} else {
idUser = in.readLong();
}
for
idUser = in.readLong();
fixed it.
I need help. I have two methods of shared preference. They are getList and setList.
This is setList()
public static void setList(Application activity, List<tcmb> mValuesList) {
StringBuilder valuesBuilder = new StringBuilder();
/*Log.d(TAG, "List Size ------ \t: " + mValuesList.size());*/
for (tcmb s : mValuesList) {
valuesBuilder.append(s);
valuesBuilder.append(",");
Log.d(TAG, "setValuestcmb: " + valuesBuilder.toString());
}
SharedPreferences values = activity.getSharedPreferences("dd", MODE_PRIVATE);
SharedPreferences.Editor editor = values.edit();
editor.putString("ss", valuesBuilder.toString());
editor.apply();
}
This is getList()
public static List<tcmb> getList(Activity a) {
SharedPreferences values = a.getSharedPreferences("dd", MODE_PRIVATE);
String wordsString = values.getString("ss", "");
/* Log.d(TAG, "wordsString \t:" + wordsString);*/
String[] itemWords = wordsString.split(",");
List<String> itemList = new ArrayList<String>();
itemList.addAll(Arrays.asList(itemWords));
dovizList = (List)itemsList;
Log.d(TAG, "getValuestcmb: " + dovizList.size());
return dovizList;
}
For the values I got, I run the setList method in the asyncTask class of Main Activity that assigns to shared preference.
Then for I get to values, I run the getList method in the asyncTask class of Fragment.
And I get the object values.namely, I can see the values I get from the logcat.
[com.example.lscodex.ddddd.Model.tcmb#4ff695, com.example.lscodex.ddddd.Model.tcmb#b6b93aa, com.example.lscodex.ddddd.Model.tcmb#347db9b, com.example.lscodex.ddddd.Model.tcmb#f63eb38, com.example.lscodex.ddddd.Model.tcmb#4866711, com.example.lscodex.ddddd.Model.tcmb#8c74076, com.example.lscodex.ddddd.Model.tcmb#3be9677, com.example.lscodex.ddddd.Model.tcmb#10882e4, com.example.lscodex.ddddd.Model.tcmb#8d9634d, com.example.lscodex.ddddd.Model.tcmb#b5eee02, com.example.lscodex.ddddd.Model.tcmb#b7c2313, com.example.lscodex.ddddd.Model.tcmb#a3ce950, com.example.lscodex.ddddd.Model.tcmb#ee5e749, com.example.lscodex.ddddd.Model.tcmb#fd1e84e, com.example.lscodex.ddddd.Model.tcmb#b7bdd6f, com.example.lscodex.ddddd.Model.tcmb#40f4a7c, com.example.lscodex.ddddd.Model.tcmb#b1caf05, com.example.lscodex.ddddd.Model.tcmb#b683b5a, com.example.lscodex.ddddd.Model.tcmb#f12e18b]
totally 19 values.
But when I cast values to recylerView's bindHolder in the fragment class, I get an error is that
java.lang.ClassCastException: java.lang.String cannot be cast to com.example.lscodex.ddddd.Model.tcmb
This is asyncTask from fragment
private class DownloadXmlTask extends AsyncTask<Void, Integer, List<tcmb>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressBar.setVisibility(View.VISIBLE);
}
#Override
protected List<tcmb> doInBackground(Void... voids) {
return SharedPreferenceValues.getList(getActivity());
}
#Override
protected void onPostExecute(List<tcmb> tcmb) {
if (tcmb.size() == 0) {
mtcmbList = tcmb;
setupAdapter();
mRecyclerViewAnim.runLayoutAnimation(getContext(), mRecyclerView);
mProgressBar.setVisibility(View.INVISIBLE);
} else if (mRecyclerView != null) {
mtcmbList.addAll(tcmb);
Log.d(TAG, "onPostExecute: " + mtcmbList.size());
mRecyclerView.getAdapter().notifyDataSetChanged();
dateUpdate();
mRecyclerViewAnim.runLayoutAnimation(getContext(), mRecyclerView);
mProgressBar.setVisibility(View.INVISIBLE);
mSwipeRefreshLayout.setRefreshing(false);
}
}
}
and the place where I got the error.
#Override
public void onBindViewHolder(tcmbHolder holder, int position) {
tcmb tcmb= mtcmbList.get(position); ---- the error here
holder.bindTcmb(tcmb);
I don't know why?
EDIT
I try it with the shared preferences, I get XML list data from splash screen and import it into other activity.
private class splashTask extends AsyncTask<Void, Integer, List<tcmb>> {
private Activity mContext;
public splashTask(Activity c){
this.mContext = c;
}
#Override
protected void onPreExecute() {
mSplashProgressBar.setProgress(0);
}
#Override
protected List<tcmbDoviz> doInBackground(Void... voids) {
List<tcmb> tcmbList = new ConnectionXmlParser().getXmlFile(getApplicationContext());
try {
int getvalues = ConnectionXmlParser.howLong();
Log.d(TAG, "doInBackground: " +getvalues);
for (int i=0;i<getvalues;i++){
Log.d(TAG, "doInBackground: " +i);
publishProgress(((int)i*100)/getvalues);
Log.d(TAG, "Publishing " + ((int)i*100/getvalues));
}
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
return tcmbList;
}
#Override
protected void onPostExecute(List<tcmbDoviz> list) {
mtcmbList.addAll(list);
SharedPreferenceValues.setValuesList(getApplication(),mtcmbList);
splashScreen();
mSplashProgressBar.setVisibility(View.GONE);
}
#Override
protected void onProgressUpdate(Integer... values) {
mSplashProgressBar.setProgress(values[0]);
super.onProgressUpdate(values);
}
You are trying to change List<String> to List<tcmb> and problem lies here
public static List<tcmb> getList(Activity a){
// your code
//
List<String> itemList = new ArrayList<String>();
itemList.addAll(Arrays.asList(itemWords));
dovizList = (List)itemsList;
Log.d(TAG, "getValuestcmb: " + dovizList.size());
return dovizList;
Also, I don't understand, what exactly you are trying to achieve here.
List<String> itemsList = new ArrayList<String>();
dovizList = (List)itemsList;
But, as per code shared, you need to change
List<String> itemsList = new ArrayList<String>();
to
List<tcmb> itemsList = new ArrayList<tcmb>();
And, you don't need
dovizList = (List)itemsList;
I found how to do it.
to save XML List object with Shared Preferences in splashscreen.activity
public static void setValues(Context context, List<tcmb> curProduct){
Gson gson = new Gson();
String jsonCurProduct = gson.toJson(curProduct);
SharedPreferences sharedPref = context.getSharedPreferences("Prefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("dd", jsonCurProduct);
editor.apply();
Log.d(TAG, "setValues: " + jsonCurProduct);
}
then, to get the List object with Shared Preferences in the fragment
public static List<tcmb> getValuesAltın(Context context){
Gson gson = new Gson();
List<tcmbDoviz> productFromShared = new ArrayList<>();
SharedPreferences sharedPref = context.getSharedPreferences("Prefs", Context.MODE_PRIVATE);
String jsonPreferences = sharedPref.getString("dd", "");
Type type = new TypeToken<List<tcmb>>() {}.getType();
productFromShared = gson.fromJson(jsonPreferences, type);
return productFromShared;
}
finally, Thanks, Ravi.
I have an object called Order which I want to pass between activities. Currently I am using Parcelable to do so.
public class Order implements Parcelable {
private String email;
private Long timestamp;
private List<OrderItem> items;
public Order() { }
private Order(Parcel in) {
email = in.readString();
timestamp = in.readLong();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(email);
if (timestamp == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeLong(timestamp);
}
dest.writeTypedList(items);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<Order> CREATOR = new Creator<Order>() {
#Override
public Order createFromParcel(Parcel in) {
return new Order(in);
}
#Override
public Order[] newArray(int size) {
return new Order[size];
}
};
// Getters
...
}
The items field is a List of OrderItem objects which implement the Parcelable interface.
public class OrderItem implements Parcelable {
private String orderedClothingId;
private int quantity;
public OrderItem() { }
public OrderItem(String orderedClothingId, int quantity) {
this.orderedClothingId = orderedClothingId;
this.quantity = quantity;
}
private OrderItem(Parcel in) {
orderedClothingId = in.readString();
quantity = in.readInt();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(orderedClothingId);
dest.writeInt(quantity);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<OrderItem> CREATOR = new Creator<OrderItem>() {
#Override
public OrderItem createFromParcel(Parcel in) {
return new OrderItem(in);
}
#Override
public OrderItem[] newArray(int size) {
return new OrderItem[size];
}
};
}
Now to pass an Order object called order from one activity to another I do the following:
Intent intent = new Intent(mContext, ActivityTwo.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(ORDER_DETAIL_INTENT_EXTRA_KEY, order);
mContext.startActivity(intent);
In ActivityTwo I collect the Order object like so:
Bundle data = getIntent().getExtras();
assert data != null;
mOrder = data.getParcelable(ORDER_DETAIL_INTENT_EXTRA_KEY);
However, when I log the items field contained in the Order object in ActivityTwo it is null. How do I pass the original non-null Order object between activities without the items list being null?
First you miss to read the array back with dest = in.readTypedList(emptyList, CREATOR);
But second and more important, you need to write/read the same ammount of arguments, since you have a if in your writeToParcel you need the same when reading:
private Order(Parcel in) {
email = in.readString();
if(in.readByte() == 1)
timestamp = in.readLong(); //here to skip just like the writeToParcel
in.readTypedList(items = new ArrayList<OrderItem>(), OrderItem.CREATOR);
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(email);
if (timestamp == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeLong(timestamp);
}
dest.writeTypedList(items);
}
From first glance it looks like you are passing different different keys within your parcelable
ORDER_DETAIL_INTENT_EXTRA_KEY in the first and CLOTHING_ADMIN_DETAIL_INTENT_EXTRA_KEY in the 2nd. They should both be the same, so pick which one.
Also you can use getIntent().getParcelableExtra() instead of having to use a Bundle
I'm attempting to make an app, and at this point in the app I'm launching an activity, and adding some parcelable extras to the activity. However, with the addition of my extras, the intent will not start the activity. Commenting the putExtra line allows it to function. There is no error to speak of, and the application simply loops and allows the use of the previous activity again.
The problem code lies here:
//puzOut is a Puzzle object (code below)
intent intent = new Intent(ChooseActivity.this, GameActivity.class);
intent.putExtra("puzzle", puzOut); // <- prevents activity starting
startActivity(intent);
The data in putExtra is an object from my app, Puzzle. Below is the code for that, including the Parcelling code.
public class Puzzle implements Parcelable{
private String Name;
private String pictureSet;
private Fruit_Tile[] fruitArray;
int rows;
int columns;
public Puzzle(String puzzleId, String picSet, Fruit_Tile[] array, int rowCount, int columnCount)
{
Name = puzzleId;
pictureSet = picSet;
fruitArray = array;
rows = rowCount;
columns = columnCount;
}
private Puzzle(Parcel in) {
Name = in.readString();
pictureSet = in.readString();
Parcelable[] parcelableArray = in.readParcelableArray(Fruit_Tile.class.getClassLoader());
//Fruit_Tile[] results = null;
if(parcelableArray != null)
{
fruitArray = Arrays.copyOf(parcelableArray, parcelableArray.length, Fruit_Tile[].class);
}
rows = in.readInt();
columns = in.readInt();
}
public String getName()
{
return Name;
}
public String getPictureSet()
{
return pictureSet;
}
public Fruit_Tile[] getFruitArray()
{
return fruitArray;
}
public int getRows()
{
return rows;
}
public int getColumns()
{
return columns;
}
#Override
public void writeToParcel(Parcel out, int flags){
out.writeString(Name);
out.writeString(pictureSet);
out.writeParcelableArray(fruitArray, flags);
out.writeInt(rows);
out.writeInt(columns);
}
public static final Parcelable.Creator<Puzzle> CREATOR = new Parcelable.Creator<Puzzle>(){
public Puzzle createFromParcel(Parcel in) {
return new Puzzle(in);
}
public Puzzle[] newArray(int size) {
return new Puzzle[size];
}
};
#Override
public int describeContents()
{
return 0;
}
}
The puzzle object uses another object, Fruit_Tile, which I have also tried to make parcellable. Below is the code for that.
public class Fruit_Tile implements Parcelable
{
private Bitmap fruit;
private int x_Position;
private int y_Position;
public Fruit_Tile(Bitmap fruitInput, int x, int y)
{
fruit = fruitInput;
x_Position = x;
y_Position = y;
}
private Fruit_Tile(Parcel in)
{
fruit = Bitmap.CREATOR.createFromParcel(in);
x_Position = in.readInt();
y_Position = in.readInt();
}
public Bitmap getImage()
{
return fruit;
}
public void setImage(Bitmap input)
{
fruit = input;
}
public int getX_Position()
{
return x_Position;
}
public int getY_Position()
{
return y_Position;
}
public void setX_Position(int x) { x_Position = x; }
public void setY_Position(int y) { y_Position = y; }
public int describeContents()
{
return 0;
}
#Override
public void writeToParcel(Parcel out, int flags)
{
fruit.writeToParcel(out, flags);
out.writeInt(x_Position);
out.writeInt(y_Position);
}
public static final Parcelable.Creator<Fruit_Tile> CREATOR = new Parcelable.Creator<Fruit_Tile>(){
public Fruit_Tile createFromParcel(Parcel in){
return new Fruit_Tile(in);
}
public Fruit_Tile[] newArray(int size){
return new Fruit_Tile[size];
}
};
}
When I debug and step, following the line
startActivity(intent);
if I step continually, the program eventually returns to the Looper.java code and loops. I can then access the UI again of the first activity, and start the whole process again.
Why is my activity not starting with this putExtra line? There are no errors to speak of (that I have been able to find).
To reiterate, if the putExtra is commented out, the activity will launch.
I'd really appreciate some help!
It happens when you try to write null value in the parcel. In the following code snippet if the Name String is null it will cause activity launching issue.
out.writeString(Name);
So the solution is, either set default value of the class data members at the time of declaration. like
String Name = "";
Or at the time of writing to parcel add a check if its null then don't write it in parcel. Like
if (Name != null) {
out.writeString(Name);
}
I am currently trying to pass an ArrayList of objects from one activity to another. After much searching, I saw that you could pass things as parcels. Here is what I ended up doing:
public class PartsList extends ArrayList<Part> implements Parcelable {
public PartsList(){
}
public PartsList(Parcel in){
}
#SuppressWarnings("unchecked")
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public PartsList createFromParcel(Parcel in) {
return new PartsList(in);
}
public Object[] newArray(int arg0) {
return null;
}
};
private void readFromParcel(Parcel in) {
this.clear();
// read the list size
int size = in.readInt();
// order of the in.readString is fundamental
// it must be ordered as it is in the Part.java file
for (int i = 0; i < size; i++) {
Part p = new Part();
p.setDesc(in.readString());
p.setItemNmbr(in.readString());
p.setPrice(new BigDecimal(in.readString()));
this.add(p);
}
}
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel arg0, int arg1) {
int size = this.size();
arg0.writeInt(size);
for (int i = 0; i < size; i++) {
Part p = this.get(i);
arg0.writeString(p.getDesc());
arg0.writeString(p.getItemNmbr());
arg0.writeString(p.getPrice().toString());
}
}
}
And here is the part Object:
public class Part implements Parcelable{
private String desc;
private String itemNmbr;
private BigDecimal price;
public Part(){
}
public Part(String i, String d, BigDecimal p){
this.desc = d;
this.itemNmbr = i;
this.price = p;
}
It also has getters/setters of course.
This is where the list is created:
for (String i : tempList){
Matcher matcher = pattern.matcher(i);
while (matcher.find()){
// getting matches
String desc = matcher.group(6);
String item = matcher.group(9);
BigDecimal price = new BigDecimal(matcher.group(12).toString());
// adding the new part to the parts list
parts.add(new Part(item, desc, price));
}
}
Now, here is where it is received:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get extras (list)
Bundle b = getIntent().getExtras();
parts = b.getParcelable("parts");
// Part[] PARTS = (Part[]) parts.toArray();
final Part[] PARTS = new Part[] {
new Part("desc", "item id", new BigDecimal(0))
};
final String[] COUNTRIES = new String[] {
"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra"
};
setListAdapter(new ArrayAdapter<Part>(this, R.layout.list_item, PARTS));
ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
Toast.LENGTH_SHORT).show();
}
});
}
If I don't use the parcel, and just use the array - it works fine. I commented out my test list and it worked fine, otherwise it crashed.
// parts.add(new Part("desc", "item id", new BigDecimal(0)));
// parts.add(new Part("desc2", "item id2", new BigDecimal(1)));
// parts.add(new Part("desc3", "item id3", new BigDecimal(2)));
// create a new bundle
Bundle b = new Bundle();
// put the list into a parcel
b.putParcelable("parts", parts);
Intent i = new Intent(SearchActivity.this, Results.class);
// put the bundle into the intent
i.putExtras(b);
startActivity(i);
Did I do something wrong with the implementation of the Parcel? I can't figure this out. If anyone could help me ASAP - that would be amazing.
In your implementation of Parcelable.Creator, this looks sketchy:
public Object[] newArray(int arg0) {
return null;
}
I believe it should be:
public Object[] newArray(int arg0) {
return new PartsList[arg0];
}
You also need to define your CREATOR object for Part if you're going to declare it to implement Parcelable (although I'm not sure why it needs to).