I'm working with custom parcelable class. I need to pass this class as array to another activity and new fragments. I googled, but I found arrayList but not arrays. Please mind that I need to pass arrays not Array lists. How to achieve that? Please mind again, performance is a big issue. So any solutions with less performance consumption is very welcome.
Any helps would be very appreciated.
You can pass your arrayList as below snipts.
TestFragment testFragment = new TestFragment();
Bundle args = new Bundle();
args.putSerializable("parsedData", (Serializable)mTestModelList);
testFragment.setArguments(args);
And Get these parcable data in Model as like below:
mTestModelList = (List<TestModel>)getArguments().get("parsedData");
YES, Serialisation is slow bit than Parcelable.
And you can implement that using parceler
Of course, the ParcelWrapper can be added to an Android Bundle to transfer from Activity to Activity using this:
Bundle bundle = new Bundle();
bundle.putParcelable("example", Parcels.wrap(example));
And dereferenced in the onCreate() method:
Example example = Parcels.unwrap(getIntent().getParcelableExtra("example"));
You can get more detail of performance related to Parcelable vs Serializable here.
Here is the write answer
// write parcelable array
final Bundle arguments = new Bundle();
MyParcelable[] myArray = new MyParcelable[10];
arguments.putParcelableArray("key"myArray);
// read parcelable array
MyParcelable[] myArray = (MyParcelable[])getArguments().getParcelableArray("key");
use like following class of your parcealble array
public class ParcelableLaptop implements Parcelable {
private Laptop laptop;
public Laptop getLaptop() {
return laptop;
}
public ParcelableLaptop(Laptop laptop) {
super();
this.laptop = laptop;
}
private ParcelableLaptop(Parcel in) {
laptop = new Laptop();
laptop.setId(in.readInt());
laptop.setBrand(in.readString());
laptop.setPrice(in.readDouble());
laptop.setImageBitmap((Bitmap) in.readParcelable(Bitmap.class
.getClassLoader()));
}
/*
* you can use hashCode() here.
*/
#Override
public int describeContents() {
return 0;
}
/*
* Actual object Serialization/flattening happens here. You need to
* individually Parcel each property of your object.
*/
#Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(laptop.getId());
parcel.writeString(laptop.getBrand());
parcel.writeDouble(laptop.getPrice());
parcel.writeParcelable(laptop.getImageBitmap(),
PARCELABLE_WRITE_RETURN_VALUE);
}
/*
* Parcelable interface must also have a static field called CREATOR,
* which is an object implementing the Parcelable.Creator interface.
* Used to un-marshal or de-serialize object from Parcel.
*/
public static final Parcelable.Creator<ParcelableLaptop> CREATOR =
new Parcelable.Creator<ParcelableLaptop>() {
public ParcelableLaptop createFromParcel(Parcel in) {
return new ParcelableLaptop(in);
}
public ParcelableLaptop[] newArray(int size) {
return new ParcelableLaptop[size];
}
};
}
now make Arraylist of ParcelableLaptop and put in the bUndle with argument
intent.putParcelableArrayListExtra("laptop", parcelableLaptopArray);
Where parcelableLaptop is your Arraylist of the Model. And to get the List:
Intent intent = getIntent();
ArrayList<ParcelableLaptop> parcelableLaptop = (ParcelableLaptop) intent
.getParcelableArrayListExtra("laptop");
Related
I have this custom object which I want to pass to a different Activity:
public class FindRouteOutputForDisplay {
public ArrayList<VertexDisplay> vertexDisplayArrayList;
public ArrayList<Integer> integerArrayList;
}
I tried this, but doesn't work.
Intent newIntent = new Intent(FirstActivity.this, SecondActivity.class);
FindRouteOutputForDisplay data = getMyData();
newIntent.putExtra("data", data); // Error
startActivity(newIntent);
Should I pass
public ArrayList<VertexDisplay> vertexDisplayArrayList;
public ArrayList<Integer> integerArrayList;
separately one-by-one? Any way to pass all of them at once?
You can try this solution.
public class FindRouteOutputForDisplay implements Serializable{
public ArrayList<VertexDisplay> vertexDisplayArrayList;
public ArrayList<Integer> integerArrayList;
}
Intent newIntent = new Intent(FirstActivity.this, SecondActivity.class);
FindRouteOutputForDisplay data = getMyData();
newIntent.putSerializable("data", data);
startActivity(newIntent);
If you have any errors on "putSerializable" so you can cast your object to Serializable in this way.
newIntent.putSerializable("data", (Serializable)data);
And in your activity just get your data by this
FindRouteOutputForDisplay data = getIntent().getSerializable("data");
Hope it helps.
Save your data in your application context class. Since this class is available across your application instance, you can get or set the variables defined inside this class from all activities. More info here
Change this :
startActivity(routeDetailIntent);
To :
startActivity(newIntent);
You should make the custom objects implement the Parcelable interface:
public class MyParcelable implements Parcelable {
private int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in) {
mData = in.readInt();
}
}
You can also have a look here if you want other solutions.
I have a trick for you. Add Gson to your dependencies.
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.2.4'
}
Convert your object to Json and ship it as a String.
String data = new Gson().toJson(getMyData())
Convert it back from String in a new Activity
FindRouteOutputForDisplay data = new Gson(stringData, FindRouteOutputForDisplay.class).
You can make the class static and use it anywhere in your app.
you have passed wrong intent to start activity.
Intent newIntent = new Intent(FirstActivity.this, SecondActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable("value", data );
newIntent.putExtras(bundle);
startActivity(newIntent );
I also face this problem so I'm trying this below code:
Pass the object with intent
In starting activity we can set the parcelable object to an intent
User user = new User("1", "u", "u", "u");
ArrayList<User> userList = new ArrayList<User>();
Sensor sensor = new Sensor("1", "s", "s", true, user, userList);
intent.putExtra("com.score.senzors.pojos.Sensor", sensor);
In destination activity we can get the parcelable object from intent extras(bundle)
Bundle bundle = getIntent().getExtras();
Sensor sensor = bundle.getParcelable("com.score.senzors.pojos.Sensor")
Hope it Helps you
I got an error as below:
Error:(133, 15) error: method setMonkeyBuisness in class QuoteBank cannot be applied to given types;
required: ArrayList<QuoteQuestion>
found: ArrayList<Parcelable>
reason: actual argument ArrayList<Parcelable> cannot be converted to
ArrayList<QuoteQuestion> by method invocation conversion
Both QuoteQuestion and QuoteBank implement Parcelable and all their methods. I cannot type cast parcelable either.
Am I using Parcelable array list correctly?
Here is some part of my code for QuoteBank:
public class QuoteBank implements Parcelable{
public static final String ARRAY_LIST_KEY = "arrayListKey";
private ArrayList<QuoteQuestion> monkeyBuisness;
public QuoteBank(){
}
#Override
public void writeToParcel(Parcel dest, int flags) {
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(ARRAY_LIST_KEY, monkeyBuisness);
dest.writeBundle(bundle);
}
public static final Parcelable.Creator<QuoteBank> CREATOR = new Creator<QuoteBank>() {
#Override
public QuoteBank createFromParcel(Parcel source) {
Bundle bundle = source.readBundle();
QuoteBank qb = new QuoteBank();
qb.setMonkeyBuisness(bundle.getParcelableArrayList(ARRAY_LIST_KEY));
return qb;
}
public void setMonkeyBuisness(ArrayList<QuoteQuestion> monkeyBuisness) {
this.monkeyBuisness = monkeyBuisness;
}
Here is QuoteQuestion code:
public class QuoteQuestion implements Parcelable{
public static final String QUOTE_TYPE = "quoteType";
public static final String QUOTE_NUMBER = "quoteNumber";
public static final String QUOTE_ARRAY = "quoteArray";
public static final String SPEAKER_ARRAY = "speakerArray";
public static final String ANSWER_INDEX_ARRAY = "answerIndexArray";
public static final String ANSWER_CHOICE_ARRAY = "answerChoiceArray";
public static final String CONTEXT_KEY = "contextKey";
public static final String CHOSEN_ANSWER = "chosenAnswer";
public static final String WORD_SPLIT = "wordSplit";
private int quoteNumber;
private String quoteType;
private ArrayList<String> quote;
private ArrayList<String> speaker;
private ArrayList<Integer> answerIndex;
private ArrayList<String> answerChoice;
private String context;
private String chosenAnswer;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
Bundle bundle = new Bundle();
// insert the key value pairs to the bundle
bundle.putInt(QUOTE_NUMBER, quoteNumber);
bundle.putString(QUOTE_TYPE, quoteType);
bundle.putStringArrayList(QUOTE_ARRAY, quote);
bundle.putStringArrayList(SPEAKER_ARRAY, speaker);
bundle.putIntegerArrayList(ANSWER_INDEX_ARRAY, answerIndex);
bundle.putStringArrayList(ANSWER_CHOICE_ARRAY, answerChoice);
bundle.putString(CONTEXT_KEY, context);
bundle.putString(CHOSEN_ANSWER, chosenAnswer);
bundle.putStringArrayList(WORD_SPLIT, wordSplitTypeA);
// write the key value pairs to the parcel
dest.writeBundle(bundle);
}
public static final Parcelable.Creator<QuoteQuestion> CREATOR = new Creator<QuoteQuestion>() {
#Override
public QuoteQuestion createFromParcel(Parcel source) {
// read the bundle containing key value pairs from the parcel
Bundle bundle = source.readBundle();
QuoteQuestion quoteQuestion = new QuoteQuestion();
quoteQuestion.setQuoteNumber(bundle.getInt(QUOTE_NUMBER));
quoteQuestion.setQuoteType(bundle.getString(QUOTE_TYPE));
quoteQuestion.setQuote(bundle.getStringArrayList(QUOTE_ARRAY));
quoteQuestion.setSpeaker(bundle.getStringArrayList(SPEAKER_ARRAY));
quoteQuestion.setAnswerIndex(bundle.getIntegerArrayList(ANSWER_INDEX_ARRAY));
quoteQuestion.setAnswerChoice(bundle.getStringArrayList(ANSWER_CHOICE_ARRAY));
quoteQuestion.setContext(bundle.getString(CONTEXT_KEY));
quoteQuestion.setChosenAnswer(bundle.getString(CHOSEN_ANSWER));
quoteQuestion.setWordSplitTypeA(bundle.getStringArrayList(WORD_SPLIT));
return quoteQuestion;
}
#Override
public QuoteQuestion[] newArray(int size) {
return new QuoteQuestion[size];
}
};
Also I have a second question while here - It seems all big multi UI apps will have almost all classes implement parcelable? as it is the only way to get data around the app? Is this best practice?
Split your statement into two, using a variable to hold the properly-typed ArrayList, like this:
ArrayList<QuoteQuestion> qq = bundle.getParcelableArrayList(ARRAY_LIST_KEY);
qb.setMonkeyBuisness(qq);
Why this works, whereas casting does not? I have no idea. If anyone knows, please replace this paragraph!
As for the second question, about implementing Parcelable all over the place: The temporary-by-design nature of all Activities and heavy usage of Intents can lead to requiring Parcelable in many places. Certain app design patterns can help mitigate the problem. For example, following MVC techniques, your application data can live within the Model, accessible via a custom class derived from Application. This allows most Activities to avoid saving & restoring bundled data, as they are simply Views of the Model, which persists across device rotations etc. This is a much bigger topic of course, with many different approaches, but hopefully this sparks some ideas.
It should suffice to write:
qb.setMonkeyBuisness(bundle.<QuoteQuestion>getParcelableArrayList(ARRAY_LIST_KEY));
I need to duplicate an ArrayList from one activity from another.
This is an ArrayList of an object that I named Dias, and it contains a String and a boolean:
Arraylist {Dias} // Dias contains(String Dias, boolean estado)
And I have to pass this ArrayList to other activity.
My Dias class:
public class Dias {
private String Dia;
private boolean estado;
//CONSTRUCTOR DE LA CLASE//
public Dias(String Dia, boolean estado) {
this.Dia = Dia;
this.estado = estado;
}
//GETTERS Y SETTERS DE LA CLASE//
public String getDia() {
return Dia;
}
public void setDia(String dia) {
Dia = dia;
}
public boolean isChekeado() {
return estado;
}
public void setChekeado(boolean chekeado) {
estado = chekeado;
}
}
My Primary Class:
public class Primera extends Activity {
ArrayList<Dias> dias = new ArrayList<Dias>();
//OnClick Method
public void lanzar2(View view){
dias.add(new Dias("Lu", false));
dias.add(new Dias("MAr", false));
Intent i = new Intent();
Bundle b = new Bundle();
b.putParcelableArrayList("arreglo", (ArrayList<? extends Parcelable>) dias);
i.putExtras(b);
i.setClass(this, ListasActivity.class);
startActivity(i);
}
}
How can I send my Arraylist to another activity?, I just don't understand how does it work(parcelable) and also I don't know the syntax to use it.
Thank you!
Another simple method is to serialize it in your own way.
For example:
If you have 5 elements in your arraylist like "hello", "how" , "are", "you", "brother". You can loop through the arraylist and make a string as hello,how,are,you,brother
String serializedString = "";
for(String anElement:arrayList)
serilaizedString = serializedString + "," +anElement;
and send it to another activity using putExtra method of Intent.
And in the receiving end, you can split the text using split(",") then you will get an array which you can change to array list again if needed.
String[] myArray = recievedString.split(",");
List<String> myList = new List<String>();
for(String anElement:myList)
myList.add(anElement);
Now you have myList as the array list.
P.S. Your strings shouldn't contain any comma though. So for cases with comma, you can use something like $ or % or what ever is comfortable for case.
You have to implement the interface Parcelable in the object Dias. You can see more about how to do it here: http://developer.android.com/reference/android/os/Parcelable.html
Besides that you would send through an Intent that you use to start the other activity the ArrayList using the method:
)">intent.putParcelableArrayListExtra(nameToSaveAs, yourList)
Then you startActivity(intent) and you can receive the data in the other activity with getIntent().getParcelableArrayListExtra(nameToSaveAs); You will probably have to cast it, but that is the basic steps to pass ArrayLists.
You can pass it either using Serialization or by using Parcelable interface. Refer to this for Parcelable interface http://developer.android.com/reference/android/os/Parcelable.html.
i make a 2D String array in main activity but i make NEW in another activity :
public class MainActivity extends Activity
{
public String[][] arr;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestpayment requestpayment=new requestpayment(getApplicationContext(), 1, 8, "boy");
TextView textView=(TextView)findViewById(R.id.text);
textView.setText(arr[1][1].toString());
}
}
In second Activity i use 2d array in this form :
int i=1;
MainActivity mainActivity=new MainActivity();
mainActivity.arr= new String[5][5];
mainActivity.arr[i][0] = FLName;
mainActivity.arr[i][1] = Old;
mainActivity.arr[i][2] = Image;
mainActivity.arr[i][3] = Gender;
mainActivity.arr[i][4] = Description
to here و Everything work good and i can use array amount in second activity.
but when use 2d-array in mainactivity in this form :
textView.setText(arr[1][1].toString());
return null :
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.../....main.MainActivity}: java.lang.NullPointerException
before , i make a ArrayList and New in another activity then i use in main activity and that work right , but for 2d array not work;
Now , how i can use this array that maked new in another activity
public String[][] arr was never initialized.
You need to do something like,
private String[][] arr = null;
public String[][] getArr()
{
if(arr == null)
{
arr = new String[5][6];
}
return arr;
}
Although I personally think you probably wanted to make an array list, or maybe a List of String arrays.
List<String[]> list = new ArrayList<String[]>();
If you wanted to send the array between activities, you should rather make a holder class that holds the array, make it parcellable, and send the holder between activities using Intent Extras. The http://www.parcelabler.com/ helps with making a class Parcelable.
You haven't shown enough code for me to say for sure, but that new call makes it look like your second class is setting up the array on a different instance of your main class; you never show any communication between them.
Okay… To answer your question. MainActivity mainActivity = new MainActivity(); Only creates an object: Instantiates the object. In the second class where you declare the String[][] you are assigning values and that is fine (although not a good design, unless a parent/child class relationship exists). If you were to call textView.setText(arr[1][1].toString()); in the second class you would have the values. But the thing is there is no call back. In other words your main class has no idea what the second class is doing.
I would look at other ways to persist your data. But if your do. You need a way for the first class to know your added values to your array. Which with out some sort of data persistence will be hard.
Why you are doing this in the first place is not clear. The problem is your design. Why are you going back and forth? There is no rhyme or reason. Create your array in the class it will be used and if it will not be used in that class use a data store to persist that data (or pass the data to the next class via an intent; but only primitive types). There are a few ways to data persist in Android. Read the multiple tutorials out there.
Think of OOP principles. Only pass info if it is necessary.. Deal with the info in the class it is created (substantiated). Hope this helps.
As others have said, the NullPointerException should be related to the fact that you are referencing different instances of the MainActivity. Please have a look at the code below, which is working only when arr is declared static AND the array creation is happening before using it in the class where it is actually declared (and not created):
public class Main {
public static void main(String[] args) {
SecondClass sc = new SecondClass();
sc.printArray(1, 1);
FirstClass fc = new FirstClass();
fc.printArray(1, 1);
}
}
class FirstClass {
public static String[][] arr;
public void printArray(int i, int j) {
System.out.println(arr[i][j]);
}
}
class SecondClass {
SecondClass(){}
public void printArray(int i, int j) {
FirstClass fc = new FirstClass();
fc.arr = new String[5][5];
for (int x=0; x<5; x++)
for (int y=0; y<5; y++)
fc.arr[x][y] = Integer.toString(x*y);
System.out.println(fc.arr[i][j]);
}
}
// okay to return empty 2d array..
//simply create one function like below
public static int[][] subsets(int input[],int index) {
if(index==input.length)
{
int arr[][]= {};
return arr;
}
I have a class called SuperMedia that implements Parcelable. One of the fields of the class is an ArrayList children. When I create a Bundle and try to pass a "SuperMedia" object from one activity to another, all the fields get passed fine with the exception of the ArrayList "children" which just shows up as being empty every time.
In my first Activity I do:
Bundle a = new Bundle();
a.putParcelable("media",media); //media is an object of type "SuperMedia" and all the "children" have been initialized and added to the array
final Intent i = new Intent("com.tv.video.subcategories");
i.putExtra("subcategories", a);
On my Second Activity I do:
Intent i = getIntent();
Bundle secondBun = i.getBundleExtra("subcategories");
SuperMedia media = secondBun.getParcelable("media"); //For some reason the ArrayList"children" field shows up as empty.
Im not sure why this is happening. If anybody can guide me on the right path that would be greatly appreciated. Below is my SuperMedia class btw.
public class SuperMedia implements Parcelable{
public URI mthumb;
public String mTitle;
public ArrayList<SuperMedia> children = new ArrayList();
public SuperMedia(URI thumb, String title) {
this.mthumb = thumb;
this.mTitle = title;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeString(mTitle);
dest.writeString(mthumb.toString());
dest.writeTypedList(children);
}
public static final Parcelable.Creator<SuperMedia> CREATOR = new Parcelable.Creator<SuperMedia>() {
public SuperMedia createFromParcel(Parcel in) {
return new SuperMedia(in);
}
public SuperMedia[] newArray(int size) {
return new SuperMedia[size];
}
};
private SuperMedia(Parcel in) {
mTitle = in.readString();
try {
mthumb = new URI(in.readString());
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
in.readTypedList(children, SuperMedia.CREATOR);
}
public SuperMedia(){
}
}
If you want simply pass object through intent then you can make SuperMedia Serializable no need to Parcelable.
public class SuperMedia implements Serializable{...}
put it as
Bundle a = new Bundle();
a.putSerializable("media",media);
and we get it as.
Intent i = getIntent();
Bundle secondBun = i.getBundleExtra("subcategories");
SuperMedia media = (SuperMedia)secondBun.getSerializable("media");
if you really needed Parcelable then may it help you.
Arraylist in parcelable object
Use Bundle's putParcellableArrayList for storing SuperMedia object
Bundle args = new Bundle();
args.putParcelableArrayList("media", "media");
and for restroring
getArguments().getParcelableArrayList("media");
This way will ensure bundle save your list objects as implemented in parcelable instance.
Also, be aware of using only ArrayList, other List subclasses not supported.