-
Notifications
You must be signed in to change notification settings - Fork 37
We're missing a third Context that can be included in view subclasses #54
Comments
I’m pretty sure that creating widgets with the application context doesn’t work very well. It makes sense, because for GUI you need a GUI context, which pertains to the If you have tried using just the application context and succeeded, I would be interested in your findings :)
This thing also annoys me, but at the time I haven’t found a good way to unify the two. I wish Android separated the different
The problem here is that if you have a general type like
This one should be straightforward to fix in the macro, good point. |
Is there an example of where the |
Oh and btw this line made me see the wisdom in having ctx.get.getTheme.resolveAttribute(styleAttr, output, true) |
Generally, passing an |
I've been thinking about this a little bit more. Since widget creation requires an |
What if it’s a |
You can legally create a |
I think we should use something like this instead of the current contexts: case class ContextWrapper(originalContext: Option[WeakReference[Context]], appContext: Context) {
def get = originalContext.flatMap(_.get) getOrElse appContext
}
object ContextWrapper {
def apply(activity: Activity): ContextWrapper =
ContextWrapper(Some(WeakReference(activity)), activity.getApplicationContext)
def apply(app: Application): ContextWrapper =
ContextWrapper(None, app)
def apply(service: Service): ContextWrapper =
ContextWrapper(Some(WeakReference(service)), service.getApplicationContext)
// + a method for FragmentApi...
} So the user of this class can choose between Thoughts? |
This implementation is more flexible (for example, it supports widget creation in Services) and requires less boilerplate. The WeakReference mechanism is still in place. See discussion in #54.
The name feels too much general given it is not trustworthy. In some cases getting app context makes big difference, for example then starting an Activity, different set of flags can be required. Name like |
@dant3 That’s a fair point. What about this? class ContextWrapper(originalContextRef: Option[WeakReference[Context]], appContext: Context) {
def original: Option[Context] = ...
def app: Context = appContext
def bestAvailable: Context = original getOrElse app
} |
Now that I think of it, case class ContextWrapper(original: WeakReference[Context], application: Context) {
def getOriginal: Context = original.get.get
def bestAvailable: Context = original.get getOrElse app
def originalIsActivity = original.get.exists(_.isInstanceOf[Activity])
def originalIsService = original.get.exists(_.isInstanceOf[Service])
}
object ContextWrapper {
...
def apply(app: Application): ContextWrapper =
ContextWrapper(WeakReference(app), app)
...
} |
Now this is fair & clean.
But getOriginal returns a |
Maybe there should be a subclasses, with |
Right, but that’s the same for
sealed trait ContextWrapper[C <: Context] {
def original: WeakReference[C]
def application: Context
def getOriginal: C = original.get.get
def bestAvailable: Context = original.get getOrElse application
def isActivity: Boolean
def isService: Boolean
def isApplication: Boolean
}
case class ActivityContextWrapper(original: WeakReference[Activity], application: Context)
extends ContextWrapper[Activity] {
def isActivity = true
def isService = false
def isApplication = false
}
case class ServiceContextWrapper(original: WeakReference[Service], application: Context)
extends ContextWrapper[Service] {
def isActivity = false
def isService = true
def isApplication = false
}
case class ApplicationContextWrapper(original: WeakReference[Application], application: Context)
extends ContextWrapper[Application] {
def isActivity = false
def isService = false
def isApplication = true
}
object ContextWrapper {
...
def apply(activity: Activity): ContextWrapper =
ActivityContextWrapper(WeakReference(activity), activity.getApplicationContext)
...
} |
This implementation is more flexible (for example, it supports widget creation in Services) and requires less boilerplate. The WeakReference mechanism is still in place. See discussion in #54.
This implementation is more flexible (for example, it supports widget creation in Services) and requires less boilerplate. The WeakReference mechanism is still in place. See discussion in #54.
Hey @sgrif, I believe my recent commit addressed your points 1 through 3, so we have one left:
|
As it stands it turns out it's quite a pain to use many of the Macroid DSLs from inside of a view subclass. There's a couple of pain points that have come out over the last day or two for me.
Things require
ActivityContext
when they don't appear to need it.Specifically the layout building DSL. I think this is a trivial one to resolve, and just have it take an
AppContext
instead, but I wanted to get your opinion on it.Unable to use things which require
AppContext
when I only have an implicitActivityContext
.This one might be a little bit less straightforward to resolve. Here's a specific case I ran into, for reference. Because I'd like to use the layout building DSL inside of my View, I've changed the signature to
class MyView(implicit ctx: ActivityContext) extends View(ctx.get)
. However, inside of my layout code, I would like to set a height of a child in DP. TheDisplayUnits
implicit requires anAppContext
. I should be able to useActivityContext
anywhere I need anAppContext
.Is there anywhere in the API that actually requires an
ActivityContext
specifically? Does it make sense to have a common parent trait that both implement and is the thing required by the APIs internally?Should we have a more general trait that can be included for things with contexts?
Specifically wondering if it makes sense to look for the structural type
getContext: Context
, and define the implicit conversion for that type in theContexts
trait.The layout DSL doesn't play nicely with implicits
The macro currently assumes that the first argument is the context, which doesn't work for the following signatures which one might want to use if they're using Macroid, since they all are technically a 0 argument constructor with 2 argument lists.
In order for my View class to be useable by Macroid, I need to take an
android.content.Context
as my first constructor argument. In order to use Macroid inside of it, I'll need an implicitActivityContext
and potentially an implicitAppContext
. That leads to this being the signature I have to write, which feels horribly redundantI'd be happy to do the legwork on any changes to resolve these if you'd like, but the problems right now are high level enough that I figured it'd warrant a discussion before any pull requests.
The text was updated successfully, but these errors were encountered: