Pass object between activity

alberto.palberto.p Alberto PiccininITMember
edited February 2013 in Android

Hi,

I use MonoDevelop 3.0.6 with Mono for Android: 4.4.55 on Windows 6.1.7601.65536 (64-bit).

I would like to pass my object to activity.

I try to extended my class object to ISerializable, but when I try to get extra data from intent I get new object.

This is my code:

            public class MisurataItem: Java.Lang.Object, Java.IO.ISerializable
            {
                           private PFData m_PF1;
                           private PFData m_PF2;
                           private double m_Dist;

                           public MisurataItem()
                           {
                           }

                           public MisurataItem(IntPtr handle, JniHandleOwnership transfer)
                                           : base(handle, transfer)
                           {
                           }

                           public void SetPF1(PFData pf)
                           {
                                           m_PF1=pf;
                           }

                           public void SetPF2(PFData pf)
                           {
                                           m_PF2=pf;
                           }


                           public void SetDist(double dist)
                           {
                                           m_Dist=dist;
                           }

                           public PFData GetPF1()
                           {
                                           return m_PF1;
                           }

                           public PFData GetPF2()
                           {
                                           return m_PF2;
                           }

                           public double GetDist()
                           {
                                           return m_Dist;
                           }



            }

First activity:

Bundle param=new Bundle();
param.PutSerializable("OBJECT", item);

Second activity:

item=(MisurataItem)this.Intent.Extras.GetSerializable("OBJECT");

Best regards

Alberto Piccinin

Posts

  • CheesebaronCheesebaron Tomasz Cielecki DKMember, Insider, University ✭✭✭✭

    A good start is to read this thread about the exact same subject: http://forums.xamarin.com/discussion/451/communicate-with-iserializable

  • Charles.INCharles.IN Charles Packiaraj INMember
    edited February 2013

    Activity 1

    var second = new Intent(this, typeof(Activity2)); second.PutExtra("RowID", Convert.ToString(RowID)); StartActivity(second);

    Activity 2

    // Add this line to the Activity 2

    string text = Intent.GetStringExtra("RowID") ?? "0";

  • alberto.palberto.p Alberto Piccinin ITMember

    Charles, I would like to pass an object, not single string, etc.

  • JonathanPryorJonathanPryor Jonathan Pryor USModerator, Xamarin Team Xamurai

    I would like to pass an object, not single string, etc.

    What do you mean by "pass an object"? Pass an object instance, or pass an object value?

    Android's Bundle mechanism doesn't allow passing shared object instances, because the Activity you're starting may be located in another process. This is why the only Bundle methods which take object instances take ISerializable or IParcelable: the instance is serialized, transferred to the new Activity, then deserialized, thus creating a copy.

    If passing a copy is desirable, then you can certainly use ISerializable or IParcelable, but I would instead suggest you use JSON or XML serialization through strings instead (it's easier).

    However, if passing a copy is not desirable, and you really want to pass around a shared instance...that's not possible through the Bundle mechanism. You will need to construct your own mechanism, e.g. by storing an object reference in a static ("global") variable.

  • CodeMonkeyCodeMonkey Adrian Estran GBMember ✭✭✭

    I do this buy storing my objects in static vars that are available to all activity's, it's probably not the most elegant approach but it works..

  • alberto.palberto.p Alberto Piccinin ITMember

    Yes I mean object instance, sorry, My object instance has another object instance member. For example I would like to pass object instance to another activity, when I select listview item

  • CodeMonkeyCodeMonkey Adrian Estran GBMember ✭✭✭

    @alberto.p Yes, you can achieve this buy assigning the object you want to pass to the next activity to a static variable somewhere in your application. The next activity should then check to see if the static object is not null, and then use it..

  • alberto.palberto.p Alberto Piccinin ITMember

    @CodeMonkey, you can explain an example? Unfortunately, I'm a newbie on android

  • CodeMonkeyCodeMonkey Adrian Estran GBMember ✭✭✭

    Declare a static object somewhere:

    public class SharedObjects
        {
            public static Object sharedObject;
        }
    

    Then when the object is selected in your list assign the object to the static var above:

    ListView.ItemClick += delegate(object sender, Android.Widget.AdapterView.ItemClickEventArgs args)
    {
    Object selectedObject = listCollection[args.Id];
    
            SharedObjects.sharedObject = selectedObject;
    
    }
    
  • alberto.palberto.p Alberto Piccinin ITMember

    @CodeMomkey thanks. Infact I used a static object accessible from another activity

  • RupertRawnsleyRupertRawnsley Rupert Rawnsley GBMember

    @CodeMonkey and @alberto.p: Statics are bad and you should feel bad.

    Consider @jonp's suggestion of using JSON instead. This would also allow you do other things like simple object passing to and from web services, which for my money makes it more versatile than the traditional Android mechanisms.

  • CodeMonkeyCodeMonkey Adrian Estran GBMember ✭✭✭
    edited August 2013

    @RupertRawnsley I think for simple use cases a static var can't be all that bad, especially if its only being accessed from two places (list and detail screen).

    There are tons of things I would love to improve in my code, but most times the business takes priority over how neat and elegant my code is.

    Of course using Fragments alleviates the need for this sort of pattern which I am now implementing.

  • RupertRawnsleyRupertRawnsley Rupert Rawnsley GBMember

    @CodeMonkey Fair enough - it's your code after all :-)

    Relying on statics, and many other anti-patterns, will hurt you in the long run. Your code will be less maintainable and less scalable. Small projects are a valid exception, but they are also a good place to experiment and improve your skills.

  • JanHesselbachJanHesselbach Jan Hesselbach DEMember

    This thread is old, but for everyone who read this:

    Don't use statics for this, cause you could get a memory leak, when the Object is still bounded to the static one. Also it is a bad style for reading, code maintenance and understanding what happends in your code. Mybe it's easier to write like this:

    StoreClass.object = myClass;
    StoreClass.name = ...;
    Intent intent = new Intent(this, ClassToCall.class);
    this.startActivity(intent);

    But it would easier to read for others:

    Intent intent = new Intent(this, ClassToCall.class);
    Bundle bundle = new Bundle();
    bundle.putParcelable(myClass);
    intent.putExtra(bundle);
    this.startActivity(intent);

    So use Parcelable or IParcelable not ISerializable (why must they add a prefix I...? for standardisation?). So, it would look like this (this is pure Java except the Interfaces, cause I'm new in Mono):

    (Sorry, I signed the following text as source, but only a small part has been correctly styled..)

    `public class MyClass : IParcelable {

    public final static Creator CREATOR = new Creator() { @Override public MyClass createFromParcel(Parcel source) { return new MyClass(source); }

      @Override public MyClass[] newArray(int size) {
         return new MyClass[size];
      }
    

    };

    // some members private String str; private int i; private AnotherParcelableClass apc; private int[] intArray; ...

    //set it to protected, cause I usually use it for parcing protected MyClass(Parcel source) { //!!! must be in the same order as it has been written to the stream str = source.readString(); i = source.readInt(); apc = source.readParcelable(AnotherParcelableClass.class.getClassLoader()); intArray = source.readIntArray(); }

    //this one comes from the interface Parcelable //flags only for public void writeToParcel(Parcel dest, int flags) { dest.writeString(str); dest.writeInt(i); dest.writeParcelable(aps) dest.writeIntArray(intArray, aFlag); } }`

  • JanHesselbachJanHesselbach Jan Hesselbach DEMember

    In the line before the last one, forget ..."//flags only for". Forgot to write something. Would be better to read this one developer.android.com/reference/android/os/Parcelable.html#PARCELABLE_WRITE_RETURN_VALUE

  • WolfgangSchreursWolfgangSchreurs Wolfgang Schreurs NLMember
    edited February 6

    My brother experienced the same problems today.

    Might be best if Xamarin created 2 methods for passing extras using Intents:

    • PutExtra(string key, string value)

    • PutExtra(string key, ISerializable object)

    That way it's clear for the end user what will be passed around successfully using Intents.

    But I don't know how easy / reliable this would be, cause I guess most wrapper classes for Android / iOS are generated using automatic tooling.

Sign In or Register to comment.