Jan 14 | 3:50 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Jan 14 | 3:55 PM |
EGHDK | has entered the room |
EGHDK |
Hey Mark, so two big "problems" I'm having. Both have to do with listViews.
|
Mark M. |
hello, EGHDK!
|
Mark M. |
go ahead
|
EGHDK |
My first problem is basically, I need to have a menu show up in a list view. It's simple. breakfast, dinner, and lunch. Every Monday the menu is the same, every tuesday the menu is the same... etc
|
EGHDK |
breakfast lunch and THEN dinner. lol
|
EGHDK |
So, I basically put these set menu's in a database.
|
Jan 14 | 4:00 PM |
EGHDK |
7 insert statements (one for each day of the week), and then each entry has three columns. breakfast, lunch, dinner.
|
EGHDK |
That is basically the first half of it. Pretty simple, and I think I'm doing it efficiently. (in regards to using a database, and not another data structure).
|
EGHDK |
The only other thing is that sometimes, the menu can change last second, so I have a web based interface settup to override a certain menu.
|
EGHDK |
That works too. I pull out the values for breakfast, lunch and dinner and store them in arrays (because they were split with commas) and then make a network call and if anything is updated, I update the proper array.
|
EGHDK |
So now, it's time to display this in a listView.
|
Ernie | has entered the room |
EGHDK |
I want three Headers (B, L, D) and have each array show up below the proper header. But I'm not sure how to do that.
|
Ernie | has left the room |
EGHDK |
I created this SO question to try and get some direction. http://stackoverflow.com/questions/21109440/con...
|
Jan 14 | 4:05 PM |
Mark M. |
you got five answers
|
EGHDK |
So I'm even more confused then when I started.
|
Mark M. |
admittedly, the answers are mostly poor
|
EGHDK |
Yeah, it wasn't the high grade answers I usually get.
|
Mark M. |
the simplest answer is to use my MergeAdapter
|
Mark M. | |
Mark M. |
Step #1: Create three ArrayAdapters, one for each array, set up to render those rows however you want
|
Mark M. |
Step #2: Create three views for the headers, however you want those to look
|
Mark M. |
Step #3: Pour them all into the MergeAdapter, using addView() (for a header), then addAdapter() (for the array to appear below the header), for each of your three header/adapter pairs
|
Mark M. |
Step #4: Put the MergeAdapter into the ListView
|
Mark M. |
Step #5: Beer
|
EGHDK |
I like step 5.
|
EGHDK |
Heh. Thanks very clear and concise. I was going nuts, because I didn't know how I can use three different arrays as my data
|
EGHDK |
So you don't think there is anything wrong with how I architectured the activity?
|
Mark M. |
the AmazingListView and the StickyListHeaders from the 5th answer are also reasonable choices, though I haven't used them
|
Mark M. |
I wouldn't have set things up quite the same way that you did, but, then again, I do not completely understand the problem domain, and therefore may be missing some bits
|
Jan 14 | 4:10 PM |
EGHDK |
True.
|
EGHDK |
My goal was basically to make sure that the list fills up with data. and then I do the network call.
|
EGHDK |
if the network call returns anything, then I need to update one of my arrays.
|
Mark M. |
I would think the right answer is to have the right data before presenting it to the user
|
EGHDK |
Do you think that will cause me any trouble?
|
Mark M. |
it will make things more complicated to code and more confusing to the user
|
Mark M. |
I'd throw up a ProgressBar, do the network I/O, then populate the ListView with the final result
|
EGHDK |
Yeah, but since the user is just me, I will be feeling it out how it works this way. I know its not the best way, since technically the menu could change right before their eyes.
|
EGHDK |
But that's the purpose of this demo app.
|
Mark M. |
if it's just you, I'd use a Post-It Note(R) and skip the app... :-)
|
EGHDK |
hahaha
|
EGHDK |
Well, knowing all of that information, and that "that" is the desired outcome of the app. How do you recommend I update lets just say the breakfast array?
|
Jan 14 | 4:15 PM |
Mark M. |
use add(), insert(), and remove() on the ArrayAdapter
|
EGHDK |
got it.
|
EGHDK |
Okay, so onto my second question!
|
EGHDK |
So I want to build a blogRoll application. I've already created an application that takes the last ten posts from a JSON api from a wordpress site, and displays it in a list.
|
EGHDK |
So this works fine... I have two problems with it. I'm unsure of how to create something that when I scroll down, it does another call for the next 10 posts. and my second problem is, that I need this to be stored persistantly. so that lets say I'm looking at it, and I go into a tunnel or elevator, I can still go through the posts. How would I go about creating something like that? A database should work...?
|
Jan 14 | 4:20 PM |
Mark M. |
with regards to the second part, that's up to you
|
Mark M. |
a database is a likely candidate
|
Mark M. |
with regards to the first part, there are various solutions floating around, like my EndlessAdapter: https://github.com/commonsguy/cwac-endless
|
EGHDK |
Well now I'm just thinking. Should I download the data, and insert it directly into the DB, then query the DB and display that?
|
Mark M. |
well, I cannot really answer that
|
Mark M. |
personally, I would not persist it
|
Mark M. |
or, I would be going with a synchronization strategy, not a "when the user pulls up the app, then do the network I/O"
|
Mark M. |
not the approach that you're going with
|
Mark M. |
there's nothing technically wrong with your approach, but it's not how I would look at the problem
|
EGHDK |
Yeah, that was my original plan. But I don't know how to go about it.
|
Mark M. |
which "that" and "it" are you referring to?
|
EGHDK |
Not going with "open the app, network call"
|
EGHDK |
I don't know how to go about a synchonozation strategy
|
Mark M. |
first, write the activity to work against a persistent store, rather than doing the network I/O itself
|
Mark M. |
again, the choice of store is up to you, and I don't know enough about a blogroll data structure to make a suggestion
|
EGHDK |
"work against a persistent store"?
|
Mark M. |
"work against a persistent store" = "query a database" OR "read a file" OR "whatevs"
|
Jan 14 | 4:25 PM |
EGHDK |
Gothca. Just making sure I was on the same page.
|
Mark M. |
then, you need to decide when you want to update that persistent store from the network, in addition to perhaps offering a manual "check now, please" option from the activity
|
Mark M. |
for example, maybe you want to update the database every 24 hours
|
Mark M. |
for that, you could use AlarmManager, triggering a service to do the network I/O and update the database
|
Mark M. |
the "check now, please" would also kick off the service to do the same thing, just on demand
|
Mark M. |
if the service detects changes (e.g., it inserted new rows), the UI needs to know about that, if the UI happens to be in the foreground
|
Mark M. |
your choices there are either to use an event bus (LocalBroadcastManager, Otto, greenrobot's EventBus, etc.) or to use a ContentProvider and a CursorLoader as the way you access the database (so it will deliver you a fresh Cursor when data changes)
|
Mark M. |
I cover event buses and thet ContentProvider/CursorLoader options in the book
|
EGHDK |
Well, the blog roll really consists of 4 things. Title, Author, Content, and Image so it's mostly text, but I think I might just store the text in the Database and not store the image
|
Jan 14 | 4:30 PM |
Mark M. |
bear in mind that if you do not download the image (e.g., to getCacheDir()), you will be unable to show it in the elevator scenario
|
Mark M. |
you can display a placeholder instead, if you prefer
|
EGHDK |
How does toGetCacheDir work?
|
Mark M. |
getCacheDir() returns a File object, pointing to a space on internal storage where you can store files
|
Mark M. |
it works just like getFilesDir(), except that the contents of getCacheDir() can be deleted if needed to free up disk space
|
EGHDK |
Let's say I get the json api of 1 blog post, I get the title, I get the author, I get the title, and I get the link to the picture. I would download the picture toGetCacheDir, and save the location of the cached image in the database?
|
Mark M. |
yes
|
EGHDK |
I'm gettin good at this!
|
EGHDK |
Awesome.
|
Jan 14 | 4:35 PM |
EGHDK |
So since I have you here... I was working on another app that uses this https://code.google.com/p/aacdecoder-android/. It starts to stream music via a link I give it in an async task. It works fine... when I'm in the activity/app. After that it behaves weird. I thought after I leave the activity that starts an asyncTask. The asynctask stops. So I plan on starting it in a service, but I'm confused to how the asyncTask still plays music even when I back out of the activity.
|
Mark M. |
why wouldn't it?
|
Mark M. |
AsyncTask is not tied to an activity lifecycle
|
Mark M. |
unless you do something to stop the task, the task will keep rolling
|
Mark M. |
until the task completes
|
EGHDK |
Whaaat. I'm so confused. I was asking around, and someone said, whatever creates a thread, if the thing that creates it dies, then so does the thread.
|
Mark M. |
well, that depends on the scope and definition of "thing"
|
Mark M. |
if "thing" = "process", your statement is correct
|
Mark M. |
if "thing" = "activity", your statement is incorrect
|
Jan 14 | 4:40 PM |
EGHDK |
Interesting. I was going off of this question I posted a while ago. http://stackoverflow.com/questions/17954383/ser...
|
EGHDK |
"A Thread should be destroyed when the Thread that started it is destroyed. So, if you start a Thread in an Activity then it should be destroyed when that Activity is destroyed or transferred to a Service. For instance, you can start music in a Thread and update the songs there but if you want it to keep playing when the Activity is destroyed then it should be moved to a Service"
|
Mark M. |
in the first quoted sentence, the implication is that *you* should destroy the thread, not that the thread *automatically* is destroyed
|
Mark M. |
at a quick glance, William Morrison's answer is better
|
EGHDK |
So let's say I have activity A and B. I go from A to B, and in B I start a hugeeeee insert/query in an async. Before the async is done... I press the back button to go back to Activity A. If I touch the GUI in postExecute will I get an error because I'm not there anymore?
|
Mark M. |
BTW, for these SO questions, you are welcome to use the new "bump" feature of your Warescription
|
EGHDK |
Oh yeah, I saw that today when I logged on. Will definitely give all of your features a try.
|
Mark M. |
does "touch the GUI" mean "call a method on the activity that started the AsyncTask"?
|
Jan 14 | 4:45 PM |
EGHDK |
Either that, or I try to update the listView that was on Activity B.
|
Mark M. |
that probably would involve calling a method on that activity
|
Mark M. |
regardless
|
Mark M. |
you usually will not get an error
|
Mark M. |
even though Activity B is destroyed, the objects still exist
|
Mark M. |
they will attempt to do the work
|
Mark M. |
but then there will be no visual result, because the activity is destroyed
|
Mark M. |
there may be some things that might cause an exception, but I cannot think of any examples
|
EGHDK |
Oh. So even though B is destroyed, AsyncTask may be holding onto some of the objects.
|
Mark M. |
AsyncTask holds onto whatever it can reach
|
Mark M. |
so, if the AsyncTask can "update the listView that was on Activity B", by definition, the instance of Activity B is still reachable
|
Mark M. |
and, hence, is not garbage collected
|
EGHDK |
So when asynctask completes, then everything in activity B will be dead. (unless static variables or something)
|
Mark M. |
everything in Activity B will be (hopefully) unreachable and therefore will be eligible for garbage collection
|
Mark M. |
when the garbage collection routines get around to it
|
EGHDK |
Gotcha.
|
EGHDK |
So if I create a huge insert statement in activity B, and then I press the home button. I can assume that it is still going to try to complete the huge insert statement?
|
Mark M. |
yes
|
EGHDK |
Beautiful. Didn't know that.
|
Jan 14 | 4:50 PM |
Mark M. |
the risk is that Android may terminate the process before the work gets done
|
EGHDK |
Okay, so the last thing is, I "risk" the insert statement not completing.
|
EGHDK |
Oh. I was right!
|
EGHDK |
So, if I NEED this insert statement to go through, I can create a service, to make sure it doesn't get killed with the application?
|
Mark M. |
it greatly increases the odds of success
|
Mark M. |
there are no guarantees in life
|
Mark M. |
I'd use an IntentService, as it gives you the background thread that you also need
|
Mark M. |
but I'd also do some performance testing
|
Mark M. |
if you feel confident that the work will get done in less than a second, your AsyncTask is probably fine
|
Mark M. |
as nothing else is likely to clobber your process quite that quickly
|
EGHDK |
True. I will keep that in mind. I started to dive into services using the Marakana Android bootcamp, but he totally lost me. He said that there are two types of services or something.
|
Mark M. |
well, depending on how you score it, there are lots of types of services
|
Mark M. |
we as developers typically focus on the plain Service and the IntentService
|
EGHDK |
And one service is used for inside apps, and another one is used for outside apps.
|
Mark M. |
ah, he was referring to whether or not a service is exported, and is available as a remote service
|
EGHDK |
Yeah. If I want to keep my music playing, would I export my service?
|
Jan 14 | 4:55 PM |
Mark M. |
only if you are expecting some third-party app to control your service
|
Mark M. |
otherwise, no
|
EGHDK |
Okay. The only thing I want to control my service is my notification.
|
EGHDK |
When I start playing music, I want a notification to show up with a stop button.
|
EGHDK |
In that case... I still don't have to export... correct?
|
Mark M. |
note that "a stop button" is only available on the expanded notifications available starting with 4.1 or so
|
Mark M. |
correct, you will not need to export the service
|
EGHDK |
yeah
|
EGHDK |
Awesome.
|
EGHDK |
Okay, thanks a lot as always.
|
Mark M. |
you are very welcome
|
EGHDK |
I always recomend your book everywhere I go! People ask me how I got so good at android. Always point them to your direction.
|
Mark M. |
many thanks!
|
EGHDK |
I also tell them that I should actually read the book more and not rely on stack overflow, but... I always have so many little questions.
|
EGHDK |
Have a good night mark. Again appreciate it!
|
Mark M. |
if you need it, the next chat is Thursday, 7:30pm US Eastern Time
|
Mark M. |
and the chat transcript should be uploaded to http://commonsware.com/office-hours/ shortly
|
Jan 14 | 5:00 PM |
Mark M. |
have a pleasant day!
|
EGHDK | has left the room |
Mark M. | turned off guest access |