Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing typed parameters between activities #98

Closed
aafa opened this issue Aug 29, 2014 · 11 comments
Closed

Passing typed parameters between activities #98

aafa opened this issue Aug 29, 2014 · 11 comments

Comments

@aafa
Copy link

aafa commented Aug 29, 2014

I'm very new to scaloid and scala but this got-typed-everything approach provided by scala is what makes development more controllable and thus exciting to me.

So when I was unable to find any scaloid-way of passing typed parameters between activities I've made my own. In my BaseActivity class I declared this two functions

def startActivityWithParam[A](o: Any)
def getParam[T: ClassTag]: T 

which goes like this

class aActivity extends BaseActivity{
....
def onClick = {
val user = new User
startActivityWithParam[bActivity](user)
}
....
}


class bActivity extends BaseActivity{
...
onCreate {
val u : User = getParam[User]
}
}

class BaseActivity extends SActivity

I've found this pair of functions very convinient so I thought it would be cool to make them part of SActivity (rather TraitContext but anyway) itself.

I'll be glad to hear any feedback on this.

@pocorall
Copy link
Owner

What is detailed implementation of startActivityWithParam and getParam?

@aafa
Copy link
Author

aafa commented Aug 29, 2014

Mine is this

abstract class CoreBaseActivity extends SActivity {
  def startActivityWithParam[A](o: Any)(implicit evidence$9: ClassTag[A], context: Context): Unit = {
    CoreBaseActivity.map.put(o.getClass.getName, o)
    super.startActivity
  }

  def getParam[T: ClassTag]: T = {
    CoreBaseActivity.map(classTag[T].runtimeClass.getName).asInstanceOf[T]
  }
}

object CoreBaseActivity {
  var map = mutable.HashMap[String, Any]()
}

@pocorall
Copy link
Owner

Using static member (object in Scala) is not a good way to pass a value between activities.

http://stackoverflow.com/questions/1636500/are-static-fields-in-activity-classes-guaranteed-to-outlive-a-create-destroy-cyc

@aafa
Copy link
Author

aafa commented Aug 29, 2014

Thanks, I was not aware of that.
But still it's doable with dedicated singleton, right?

Here is the list of all possibilities http://stackoverflow.com/questions/4878159/android-whats-the-best-way-to-share-data-between-activities

upd. official way http://developer.android.com/guide/faq/framework.html#3

@pocorall
Copy link
Owner

The object assigned in a static field is not guaranteed to be persistent. It often became null. It is surprising that the official FAQ does not mention about this.

Anyway, if you make your own singleton object, why does it need to be at SActivity class?

object UserStore {
  def user: User = ???
}

This kind of code is just enough.

@aafa
Copy link
Author

aafa commented Aug 31, 2014

why does it need to be at SActivity class

that was only my initial blunt implementation, it absolutely doesn't have to
singleton (which I mentioned early) is a good way to go here.

like for instance

object ActivityParameters {
  var storage = mutable.HashMap[String, Any]()
}

and use this storage to get parameters passed among activities

so regarding my initial thought to put those functions into scaloid - what do you think?

@alcarvalho
Copy link

+1 for the feature.

I think the best way to do this would be to make use of macros and implement it like Android Annotations does, using extras. I'll try to do that when I have time. That should be a nice way to learn macros.

@pocorall
Copy link
Owner

Recent release of Scaloid includes more convenient way to pass values between activities:

new Intent().put(valueA, valueB, valueC).start[MyActivity]

This looks more natural because it can be translated one-to-one in plain English:

Create a new Intent, and put values A, B, and C. Then, start the MyActivity.

Please refer to this blog post for more detail:

http://blog.scaloid.org/2014/10/scaloid-36-is-released.html#comment-form

@pocorall
Copy link
Owner

pocorall commented Mar 9, 2015

I believe the intent shorthand can be an effective solution for this issue, and if there are no further discussions about alternatives, I would close this issue.

@aafa
Copy link
Author

aafa commented Mar 28, 2015

new Intent().put(valueA, valueB, valueC).start[MyActivity]

That's a good step forward, but still not a type-save. In my practice I usually pass only one param across the actions (DTO), and having ability to get it by type is very convenient and secure.

So for now I'd stick with my own approach.

@pocorall
Copy link
Owner

Here I summarize the proposed solutions:

Using put(...) method

Example: new Intent().put(valueA, valueB, valueC).start[MyActivity]
Pros: Compatible with other part of Android
Cons: Need serialization to pass custom-typed object.

Using static field

Example: object MyActivity { var myObject: MyType = valueToPass }
Pros: Super easy, nothing to do with Scaloid
Cons: null check is mandatory, because Android OS could make it null.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants