May 13 | 5:55 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
May 13 | 6:05 PM |
Scott | has entered the room |
Scott |
Hi Mark, how are you?
|
Mark M. |
Fine, and you?
|
Scott |
Doing well, thanks. I just a couple of softballs for ya.
|
Mark M. |
fire away!
|
Scott |
I'm
trying to stick within Android best practices for UI, and am not sure
the best way to accomplish providing a common set of options for each
activity
|
Scott |
ie, the app consists of 5 activities, each one should be able to be launched from any other
|
Scott |
the menu for each is filled with activity context based options
|
Scott |
where would I put the selections to jump to the other activities?
|
May 13 | 6:10 PM |
Mark M. | |
Mark M. |
"Pattern 4: Action Bar"
|
Mark M. |
this is the new official advice from the core Android team on that topc
|
Mark M. |
er, topic
|
Mark M. |
now, five activities is a bit more than what they have in that Twitter app
|
Mark M. |
you may have some difficulty making an action bar with four buttons and a logo
|
Scott |
ok, that kind of a tab bar is what I had in mind, just wanted to make sure I wasn't straying from the paradigm
|
Mark M. |
you're straying into a brand new paradigm
|
Mark M. |
:-)
|
Scott |
It seems like a common practice -- do current apps that you've seen handle it in a similar manner?
|
Mark M. |
um, you mean, besides Twitter?
|
Mark M. |
I haven't noticed it anywhere else
|
Mark M. |
but, like I said, it's a new paradigm
|
Mark M. |
that blog post is barely a day old
|
Mark M. |
still has that "new paradigm smell"
|
Scott |
ha - ok, thanks
|
May 13 | 6:15 PM |
Scott |
Also,
if I am putting an image in the drawable folder that doesn't have
different sizes, can I just drop it in the -mdpi folder only and it
will be found?
|
Mark M. |
I wouldn't count on that
|
Mark M. |
create /res/drawable/ and put it in there
|
Mark M. |
that's the default folder, for drawables not tied to a density, screen size, language, etc.
|
Scott |
ok, thanks! That is all for now, appreciate the help.
|
Mark M. |
no problem!
|
May 13 | 6:20 PM |
Mike R. | has entered the room |
Mike R. |
Hi Mark
|
Mark M. |
Howdy, Mike!
|
Mike R. |
Have a few questions. Am I interrupting?
|
Mark M. |
Nope, go right ahead
|
Mike R. |
Let's start with audio. I have an activity that plays an audio file and I'm using the AudioDemo as the basis for it
|
Mike R. |
I've hooked up a start, pause and stop buttons. all works well
|
Mike R. |
What I'd like to do is display a progress bar / scrubber
|
Mike R. |
Not sure how to get callbacks as the audio file is played to show total time, current position, etc
|
Mark M. |
You don't get callbacks
|
Mark M. |
You have to poll
|
Mark M. |
If you read further in the Media chapter, you'll see the vidtry sample for streaming video
|
Mark M. |
that shows a ProgressBar being used as a timeline
|
Mike R. |
i'll try that. thanks.
|
Mark M. |
It uses postDelayed() to get control roughly once/second
|
Mark M. |
then calls getElapsedTime() and stuff to determine what to display
|
May 13 | 6:25 PM |
Mike R. |
Next is a list view.
|
Mike R. |
I have several in them in my app.
|
Mike R. |
One, which looks like all the others, is not showing the brief flash of orange to indicate selection
|
Mike R. |
can't figure out why.
|
Mark M. |
are you setting android:listSelector in the layout XML?
|
Mike R. |
is there something I should be looking for to ensure that the item selection will show
|
Mark M. |
a few things
|
Mark M. |
android:listSelector
|
Mark M. |
android:background for the widgets that make up your rows
|
Mark M. |
and whether or not those rows are reported as enabled by your adapter
|
Mark M. |
the defaults for those three all give you the orange flash
|
Mark M. |
monkey with any of them, and you may lose the flash
|
Mark M. |
of course, the monkeying may be intentional, just with unexpected side effects
|
Mike R. |
not using listSelector at all. I'll check the background on the widgets. that may be it
|
Mark M. |
background of layouts (e.g., RelativeLayout) are transparent by default
|
Mark M. |
if
you make those solid, you will need to do something about the selector
(e.g., android:drawSelectorOnTop="true" and then provide a translucent
selector in android:listSelector)
|
Mike R. |
next topic. network connectivity. Is there a simple api call to determine if the device has a connection to the network?
|
May 13 | 6:30 PM |
Scott | has left the room |
Mark M. |
android.net.ConnectivityManager
|
Mark M. |
getActiveNetworkInfo()
|
Mark M. |
if it returns null, you have no connection
|
Mark M. |
otherwise, you get a NetworkInfo with the details of your connection
|
Mike R. |
ok
|
Mike R. |
Rotation events.
|
Mike R. |
My app pretty much handles all rotations and I've got layouts for them, etc.
|
Mike R. |
However, one activity is causing me problems.
|
Mike R. |
as I understand rotation, the activity stops and recreates itself in response to a rotation event. correct?
|
Mark M. |
by default, yes -- pause->stop->destroy, then create->start->resume for a new instance
|
Mike R. |
is there some way during the onCreate call to tell if this is being done because of a rotation event?
|
Mark M. |
strictly speaking, no
|
Mark M. |
what exactly is your problem?
|
May 13 | 6:35 PM |
Mike R. |
During
my onCreate method I call another activity that does a lot of network
downloads, but I don't want to call that activity if i'm being created
solely because the device is being rotated.
|
Mark M. |
well, I'm not a huge fan of Activity A calling startActivity() for Activity B from A's onCreate()
|
Mark M. |
if that's what you have to do, I can think of two possible solutions:
|
Mark M. |
1.
In Activity A, implement onRetainNonConfigurationInstance() to
return...well, just about anything non-null. Then, in onCreate(), call
getLastNonConfigurationInstance(), and if it's not null, you know you
are being created as a result of a configuration change. 99% of the
time, that's a screen rotation.
|
Mark M. |
2.
Block the destroy/create cycle for rotations on Activity A, via the
android:configChanges attribute in the manifest, and use
onConfigurationChanged() to fix up your UI
|
Mark M. |
both of those are covered in the Rotation chapter of my Android book
|
Mike R. |
yes. i think option 1 will work for my case.
|
Mike R. |
finally, an app design question.
|
Mike R. |
my app has a lot of cases of Activity A calling Activity B which might call Activity C
|
May 13 | 6:40 PM |
Mike R. |
in
other object oriented frameworks i might create an instance of class A.
Class A might create an instance of Class B and set some of the
instance variables in Class B. Then i would invoke a method on Class B
to display some UI
|
Mike R. |
in Android I'm using an Intent and a startActivity method to display some UI
|
Mike R. |
what i'm missing is the opportunity to create an instance of class b and set some instance variable from within Activity A
|
Mike R. |
is there a way to accomplish this some other way than by using global variables?
|
Mark M. |
the ideal answer is to use Intent extras
|
Mark M. |
if what you want to pass around are not small primitives, then extras aren't a good answer
|
Mike R. |
covered in the book, i assume? :-)
|
Mark M. |
lightly
|
Mark M. |
you'll see it in the Tutorials, when we add the database (Tutorial 11 or so)
|
Mike R. |
not small primitives. more complex objects, arraylists, etc.
|
Mark M. |
then you really should consider more MVC, and move some of that stuff out to a service, or perhaps a custom Application class
|
Mark M. |
activities work best when they're fairly thin
|
May 13 | 6:45 PM |
Mark M. |
chunky activities are OK if they are all fairly independent
|
Mark M. |
inter-dependent chunky activities are your problem
|
Mike R. |
exactly. how do i learn MVC in android?
|
Mark M. |
since I'm guessing the dependency will be tough to break, you need to slim them down and move complex data to a central spot
|
Mark M. |
well, Android isn't a great MVC platform, so you wouldn't want to "learn" it on Android
|
Mike R. |
i know how to do MVC, just not on android. any good examples?
|
Mark M. |
you
can move in an MVC direction by pulling your data model out to some
classes outside any activity, so the activities hold onto just what
they need and pass identifiers around
|
Mark M. |
I don't have any great examples at the ready, that is in publicly-available code
|
Mark M. |
that tends to get more complicated than I try to profile in the books, and the places where I've done it are all consulting gigs
|
Mike R. |
I am doing that. I have all my data modeled in separate classes. but I need to pass at least arraylists to the activities
|
Mark M. |
why?
|
Mike R. |
well, for instance, one activity displays a list of articles, which it gets from an arraylist
|
Mark M. |
well, let me rephrase: why are you passing array lists *between* the activities?
|
Mark M. |
you indicated earlier, "not small primitives. more complex objects, arraylists, etc."
|
Mike R. |
the app maintains several arraylists, one for each news channel the user subscribes to .
|
May 13 | 6:50 PM |
Mike R. |
one
activity displays the list of news channels. the next activity displays
the list of articles in the channel that the user selected, etc.
|
Mark M. |
that should not involve "more complex objects, arraylists, etc."
|
Mark M. |
let's pretend this is a feed reader, so I have some terminology to work with
|
Mark M. |
your data model is a collection of Feeds, each of which has Posts
|
Mike R. |
the article itself is a complex article, with several strings, urls, images, and booleans
|
Mike R. |
as is a news channel
|
Mark M. |
that's fine
|
Mark M. |
you still should not need to pass any of that between activities
|
Mark M. |
your articles/news channels/stuff should be held someplace central, outside any activity
|
Mark M. |
such as a Service, or a custom Application class, or in a pinch a global
|
Mark M. |
the news-channel-list activity gets its information from the Service
|
Mark M. |
when the user clicks a channel, you pass a channel ID to the display-articles-list activity
|
Mark M. |
the display-articles-list activity gets the articles from the Service
|
Mark M. |
etc.
|
Mark M. |
and if all of this really is stored in a database, you dispense with the Service
|
Mark M. |
and this all just becomes queries against the database
|
Mark M. |
much like the LunchList tutorial in the Tutorials book
|
May 13 | 6:55 PM |
Mike R. |
i
can see how that might work. i was trying to avoid having to re-create
some lists for performance reasons. but i might be better off just
passing id's between activities
|
Mark M. |
then cache the lists in the Service or something
|
Mike R. |
i'll look into that. i don't think it will be too big of a design change.
|
Mike R. |
that's it for me. talk to you next time. Mike
|
Mark M. |
c-ya!
|
Mike R. | has left the room |
Mark M. | turned off guest access |