Struggling to writing my object to Parcelable - java

I am trying to send an object from one activity to another, so hence I am using parcelable, and while I have created code to send it and receive it,(the code for this is at the bottom) it seems that I need some code to be able to actually write the object to the parcel.
Error While Passing An Object From An Activity To Another (Using Parcelable)
I believe what I need to do is similar to the answer given in this, so I need a writeToParcel method, which I have done in the code below. (Although at dest.writeValue(this); is where I get an error) says StackOverFlowError
I believe i may also need public static final Parcelable.Creator... although don't completely know how to write it (I have tried to write one roughly and its the bit in comments)
Also I don't know if I need a bit that would be like public Clubs (Parcel source)...
Any help would be greatly appreciated. Thanks
public class Clubs implements Parcelable{
public void setEvent(String eventType, String date) {
this.eventType = eventType;
this.date = date;
}
//contains lots of defined variables and various methods that
//aren't relevant for my question and would take up lots of room
//all like the one above.
//public static final Parcelable.Creator CREATOR
//= new Parcelable.Creator() {
// public Parcel createFromParcel(Parcel in) {
// return (in);
// }
//};
#Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(this);
}
}
My onItemClick class that puts the object into the parcel, and starts the new activity
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
Clubs mymeeting = db.get(map.get(position));
Intent i = new Intent();
Bundle b = new Bundle();
b.putParcelable("mymeeting", mymeeting);
i.putExtras(b);
i.setClass(ListSample.this, DynamicEvents.class);
startActivity(i);
}
The start of my new activity code that will be edit later once it send the object across correctly
public class DynamicEvents extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Bundle b = getIntent().getExtras();
// Create the text view
TextView textView = new TextView(this);
textView.setTextSize(20);
textView.setText(" " + b.getParcelable("mymeeting").toString());
// Set the text view as the activity layout
setContentView(textView);
}
}

Rewrite writeToParcel method as
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(eventType);
dest.writeString(date);
}
You may not be allowed to write Custom Java Object directly. Either write standard data values individually or make your object serializable and use method writeSerializable on Parcel object.

Related

How to pass data from activity to a class?

How can i send data from an activity to a class ?
I tried to pass a String using getter but this gives me the initial value of the variable , but my String's value changes in my onCreate. Any ideas how can i pass it to my class ?
Here is some code :
public class MainActivity extends AppCompatActivity {
private String global ;
public String getGlobal() {
return global;
}
...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
global = String.valueOf(parent.getItemAtPosition(position));
}
});
}
And here is my class
public class SimpleVar {
MainActivity mainActivity = new MainActivity() ;
String data = mainActivity.getGlobal; }
Any help will be much appreciated. Thank you in advance !
global is not actually "global"
Each instance of the Activity has its own string, and the OS can decide to kill your Activity at any time and recreate it, so therefore don't rely on a variable from an Activity within another class.
Secondly, never ever make a new Activity. That is no longer tied to the Activity that you would eventually click the button on.
It's hard to determine what you really need, but this is more correct.
public class SimpleVar {
String data;
}
With the Activity sending data to it
private SimpleVar var;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
var = new SimpleVar();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
var.data = String.valueOf(parent.getItemAtPosition(position));
}
});
}
If you need that object elsewhere, you need to pass it around to those classes from this Activity
try to make constructor for your class
public class SimpleVar {
private String data;
public SimpleVar(String data) {
this.data = data;
}
public void setData(String data) {
this.data = data;
}
}
then in your activity new the class and then set data to it
You should not create new mainactivity in your class.
When on instantiating the class pass to it a reference to Activity in which the class was created. Reference to Activity should be kept in a weakreference. Then You can make a getter in the Activity and call it from Your class.
Or You can do the opposite - keep reference to the instantiated object in the Activity. Use setter from the activity to pass new values to the object.

Android - How to make an Activity for each item in a ListView and pass Java Object to next screen

I have a ListView of contacts and each contact is a Java object with a bunch of information associated with it. Some of that info is shown in the ListView, but the rest is meant for the DetailView. I'm trying to write a method that will take me to a DetailView for any contact I click on, but I also need to take the object with me. I store all of the contacts in an ArrayList in my MainActivity.java
My questions: Do I need to take the contact object with me or is there actually some way to access my ArrayList in another Activity?
If I can/have to take it with me, how would I do so, since the putExtra() methods don't take objects as arguments.
The beginning of my MainActivity looks like this:
public class MainActivity extends Activity implements AdapterView.OnItemClickListener {
ListView list;
I have a very basic onClickListener right now but don't know what to put into it:
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(MainActivity.this, DetailView.class);
intent.putExtra("contact", i);
startActivity(intent);
}
I feel like my initial definition of the MainActivity class doesn't correspond to the onItemClick method or something, which is why it doesn't execute and take me to another screen.
Intent intent = new Intent(ActivityA.this, DetailView.class);
intent.putExtra("extra_name","extra");
startActivity(intent);
Then in the other Activity :
/*onCreate*/
Object extra = getIntent().getExtra().get("extra_name");
I would recommend to pass an ID of some sort pointing to the description, passing complex data structure with intents is not recommended
Simply, use Intent.putExtra() to pass the information and getIntent().getExtras() to receive the information.
// call a new intent
myIntent = new Intent(ActivityA.this, ActivityB.class);
// put an extra (like this following string)
String userid = "User A";
myIntent.putExtra("TAG_CONTACT_ID", userid);
startActivity(myIntent);
// receive the info in your onCreate method in ActivityB
Bundle extras = getIntent().getExtras();
if(extras != null) {
String newUserID = extras.getString("TAG_CONTACT_ID");
}
See this short example for more information.
If you want to pass an Integer, you can do it as the following: myIntent.putExtra("value", i); and take it with: int myValue = extras.getInt("value");.
Hope this help.
Try something like this:
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Contact c = (Contact)contacts.get(position);
Intent i = new Intent();
i.putExtras("contact", c);
i.setClass(this, Activity2.class);
startActivity(i);
}
Create java object with parcelable
Check the below code to create parcelable object in Android.
public class ObjFeedImages implements Parcelable {
public int image_id;
public boolean like_status = false;
public String image_url = null;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] {
String.valueOf(image_id),
String.valueOf(like_status),
image_url, });
}
public ObjFeedImages(Parcel in) {
String[] data = new String[3];
int i = 0;
in.readStringArray(data);
image_id = Integer.parseInt(data[i++]);//
like_status = Boolean.parseBoolean(data[i++]);
image_url = data[i++];
}
public static final Parcelable.Creator<ObjFeedImages> CREATOR = new Parcelable.Creator<ObjFeedImages>() {
#Override
public ObjFeedImages createFromParcel(Parcel source) {
try {
return new ObjFeedImages(source);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
public ObjFeedImages[] newArray(int size) {
try {
return new ObjFeedImages[size];
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
};
}
After creating some list of such object say
ObjFeedImages object = new ObjFeedImages();
object.image_id = 1;
object.like_status = true;
object.image_url="http://some image url";
Intent intent = new Intent(/*Your Intent Info*/);
intent.putExtras("key_name",object);
startActivity(intent);
Here is the complete description.
To retrive object in other activity you have to write below code.
ObjFeedImages objectOnOtherActivity = (ObjFeedImages)getIntent().getParcelableExtra("key_name");
So ready to enjoy code.
Happy coding....

Passing class ArrayList between intents

I've created a class named "Player".
public class Player{
public String name;
public int score;
}
Everytime I click a button a new TextView is generated and also a new Player class. This is the code:
private TextView createNewTextView (String text){
final LayoutParams lparams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
final TextView newTextView = new TextView(this);
newTextView.setLayoutParams(lparams);
newTextView.setText(text);
Player newPlayer = new Player();
newPlayer.name = text;
newPlayer.score = 0;
players.add(newPlayer);
zacniIgro.putExtra("players", (ArrayList<Player>) players);
return newTextView;
}
Is this the right way to do it? I think there is a small flaw because each time a button is clicked, a new Player is added under the label of "newPlayer". How do I fix this?
And my main problem is this; how do I "unpack" the ArrayList in the second activity so that I can then manipulate with each element of the ArrayList? I tried getStringArrayListExtra() but it doesn't work. I also tried getExtras() but that also doesn't work since it retrieves a bundle. Or is that the right way? But what do I do with the bundle then?
The "label" newPlayer is only the name of a local variable which is always a different thing each time the method is run, so no problem here.
When you call putExtra() here players is interpreted as Serializable so corresponding call is getSerializableExtra("players"). Result must then be casted to an ArrayList<Player>.
To make this work you must additionally make Player class serializable. Here you can just implement interface Serializable.
The better way to do this is with Parcelable.
Simple example:
public class Device implements Parcelable {
private String name;
private String hash;
/**
* Default private constructor.
*/
public Device() {
}
public Device(final Parcel parcel) {
super();
readFromParcel(parcel);
}
public static final Parcelable.Creator<Device> CREATOR = new Parcelable.Creator<Device>() {
#Override
public Device createFromParcel(final Parcel source) {
return new Device(source);
}
#Override
public Device[] newArray(final int size) {
return new Device[size];
}
};
#Override
public int describeContents() {
return hashCode();
}
#Override
public void writeToParcel(final Parcel parcel, final int flags) {
parcel.writeString(name);
parcel.writeString(hash);
}
private void readFromParcel(final Parcel parcel) {
this.name = parcel.readString();
this.hash = parcel.readString();
}
Put your object in intent like this:
intent.putParcelableArrayListExtra("Key", YourObject);
To Get in another screen:
Intent intent = getIntent();
intent.getParcelableArrayExtra("key");

Java hierarchy inside an android listner

In my android application I want to solve the following scenario.
class Login extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutBuilder objLB=new LayoutBuilder(this);
objLB.createSpinner();
}
public void spinnerItemSelectedEvent(AdapterView<?> parent, View view,
int pos, long id)
{
}
}
class LayoutBuilder {
private Activity objActivity;
public LayoutBuilder(Activity a) {
objActivity = a;
}
public void createSpinner() {
final Spinner objSPItem = new Spinner(objActivity);
objSPItem.setOnItemSelectedListener(
new Spinner.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id)
{
// Do some common activity
objActivity.spinnerItemSelectedEvent(parent,view,pos,id);
// calling this for do some additional task
}
public void onNothingSelected(AdapterView<?> arg0) {}
});
objActivity.spinnerItemSelectedEvent()
}
}
and the problem is when i try to access spinnerItemSelectedEvent(parent,view,pos,id) from the 'onItemSelected' listner inside createSpinner method
I got the following error.
The method spinnerItemSelectedListener(AdapterView, View, int, long) is undefined for the type Activity
but out side the listner the access to the method works ok(neglect parameter list). What is the reason behind that? is any alternate way exist for solving this? plz help
Activity in android represents a screen. You are making a variable objActivity of type Activity whereas it should be of type Login where the function spinnerItemSelectedEvent() is declared. Change the following lines:
private Activity objActivity;
to
private Login objActivity;
and your code should run.
EDIT
Have a BaseActivity and let all your other activities extend this BaseActivity. To make the function spinnerItemSelectedEvent() reusable declare it in the BaseActivity and you can use it the way you are trying to do it now.
Example:
class BaseActivity extends Activity{
public void spinnerItemSelectedEvent(AdapterView<?> parent, View view,
int pos, long id){ }
}
class Login extends BaseActivity{
public void spinnerItemSelectedEvent(AdapterView<?> parent, View view,
int pos, long id){ //Local implementation of the function}
}
class LayoutBuilder {
private BaseActivity objActivity;
}
The problem is that inside LayoutBuilder, you have declared objActivity to be an Activity. Declare it to be a Login and all should be fine:
class LayoutBuilder {
private Login objActivity;
public LayoutBuilder(Login a) {
objActivity = a;
}
. . .
EDIT
If you want your LayoutBuilder class to be reusable by other activities, then one way to do this is via an interface declaration. For instance:
public interface SpinnerSelectionHandler {
void spinnerItemSelectedEvent(AdapterView<?> parent, View view,
int pos, long id);
}
Then declare Login as:
public class Login extends Activity implements SpinnerSelectionHandler {
. . .
Finally, redefine LayoutBuilder to take a SpinnerSelectionHandler in its constructor:
class LayoutBuilder {
private Activity objActivity;
private SpinnerSelectionHandler selectHandler;
public LayoutBuilder(Activity a, SpinnerSelectionHandler handler) {
objActivity = a;
selectHandler = handler;
}
And then replace
objActivity.spinnerItemSelectedEvent(parent,view,pos,id);
with
spinnerHandler.spinnerItemSelectedEvent(parent,view,pos,id);
Plus, if you don't need the Activity reference for anything else, you can get rid of it from the LayoutBuilder class.

Best way to store list of activities to be called from another activity

I have following goal: From a list in main activity that extends ListActivity, I want to start other activities.
This is the code of the main activity:
public class SelectionWidgetsExampleActivity extends ListActivity {
private Class[] demos = {ListViewDemo.class, ChecklistDemo.class};
private ArrayAdapter<Class> aa;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
aa = new ArrayAdapter<Class>(this, android.R.layout.simple_list_item_1, demos);
setListAdapter(aa);
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(this, demos[position]);
startActivity(intent);
}
}
My question is
How would you solve the issue of having list of classes to be executed outside the code of the main activity?
My first idea was to put it into xml resource file as string array. I can then easily create array of Strings from the resource, but don't know how to convert the string to the class - I need something like:
SomeJavaClass.getMeClassFromString(demos[position])
Do you need Class#forName(String className)?
It will solve your issue.
But what's wrong with your initial (posted) solution? I'd rather keep it than use dynamic class loading, only would changed modifiers of demos to private static final.

Categories