Office Hours — Today, July 8

Thursday, July 3

Jul 8
7:20 PM
Mark M.
has entered the room
Mark M.
turned on guest access
7:30 PM
EGHDK
has entered the room
Mark M.
hello, EGHDK
how can I help you today?
EGHDK
Hey Mark. So I finally got to Threads in my java book. So now I have a few questions regarding them and how to use them in Android.
So my first question is... why are there seemingly two ways to start a new thread?
Mark M.
could you be more specific?
EGHDK
Thread can be extended, and then override the run method... or create a thread and pass in a runnable.
Mark M.
the default implementation of run() on Thread presumably just delegates to the supplied Runnable
this allows you use composition (a Thread holds a Runnable) or inheritance (a Thread knows how to run itself) to provide the actual guts of what the thread does
but, beyond that, you'd have to ask the authors of Java
EGHDK
Interesting.
Is anyway better than another?
Jeff G.
has entered the room
Mark M.
(hello, Jeff -- I'll be with you in a moment!)
EGHDK
lately all I've been doing is new Thread(new Runnable() //overide run method)).start()
Jeff G.
ok.
Mark M.
EGHDK: that's a matter of personal preference
EGHDK
But I saw that I could just make a class of Thread and override run() in Thread... Okay. I guess I'm just looking too far into it.
7:35 PM
Mark M.
let me take a question from Jeff, and I'll be back with you in a bit
7:35 PM
Mark M.
Jeff: your turn! do you have a question?
Jeff G.
Yes.
I wanted to know if there is a way to use Manifest Merger (or perhaps something else) to selectively choose intents to use from an included library or from the main project itself. perhaps based on category?
Mark M.
I haven't delved too deeply into it
my guess is probably not
Jeff G.
as an alternative, is there a runtime way to selectively choose between intents?
Mark M.
could you explain a bit more about what you mean?
Jeff G.
Well, I'm trying to place a bunch of "reusable" stuff in a library that can be used by multiple projects, but sometimes I want the projects to override the default behavior placed in the library.
So, for example, if the project handles an intent, I don't want the library to cause the chooser dialog to pop up for a given intent. I just want the end project to handle it.
Mark M.
ah, I see
that I think you can accomplish
7:40 PM
Jeff G.
what is the best method?
Mark M.
best? heck, I'm glad I can come up with one method :-)
see the "Element markers examples" section
Jeff G.
I think I read that before (have to check again it's been awhile). It would be cool if I could use the markers for categories.
Mark M.
that may not be possible
in fact, I suspect that you may need to wipe out all <intent-filter> elements for a particular activity in the library that you are overriding
but, again, I haven't played with this in any depth yet
Jeff G.
ok. perhaps there is a different way to get those things imported into my project as defaults.
Mark M.
and it'd be high on my list, if it weren't for migrating a whole book to Android Studio :-)
Jeff G.
ahh, yes.
good luck with that. i hope it will be included in my existing subscription! :)
Mark M.
so long as it runs through early September, yes
let me swing back to EGHDK, and I'll come back to you in a bit
Jeff G.
I guess I should stop looking for typos in the old version. :)
no prob. thanks.
Mark M.
EGHDK: your turn! do you have another question?
EGHDK
Okay, so... Thread is a class, and Runnable is an interface... correct?
Mark M.
correct
EGHDK
The only method Runnable has is run... so why would you use a Runnable... except for a new Thread?
Mark M.
well, Android uses it in various other places, like post(), postDelayed(), runOnUiThread(), etc.
7:45 PM
Mark M.
in the world before Java 8, it's the classic way of bundling up a chunk of semi-arbitrary code into an object that can be passed around
7:45 PM
EGHDK
Hmm... okay. So it's not used exclusively for new Thread(Runnable run)
Mark M.
correct
there's probably places in standard Java other than Thread that take a Runnable, though my brain is somewhat fuzzy at the moment and I'm not thinking of any
OK, since we seem to have hit a lull, let me switch back to Jeff, and I'll return to you in a bit
Jeff: do you have another question?
Jeff G.
Yes.
I've got a listview with data rows that have a lot of textview items. This is more or less a design issue, so it may not be the right venue to ask this. But I'd like to know how to best align textviews so they look "clean."
Mark M.
align them with respect to what?
Jeff G.
I use relative layouts now but I'm thinking some of the stuff should be "right-aligned" just to look good.
7:50 PM
EGHDK
Okay, so this brings me to my main question. I have a method I came up with called fetchContacts() in my ContactManager class. It runs fine on most of my devices... but on devices like the moto g, and say 8k contacts the method takes about 3 seconds to run and it hangs the UI. From what I can see, the GC slows things down, because in logcat it looks like GC gets called like 4 times. I initially just put my fetchContacts() method call in new Thread(new Runnable() @override run(){fetchContacts()}).start(). Then I got the error "Can't create handler inside thread that has not called Looper.prepare()" Now... I
Mark M.
um, why not right-align them using your RelativeLayout?
Jeff G.
well, some stuff is left aligned in the cell, but anything to the right just looks oddly placed.
EGHDK
Sorry, typing up my question didn't mean to hit enter
Jeff G.
how to you right-align?
Micalet
has entered the room
Mark M.
android:layout_alignParentRight="true"
Micalet
Hello
Jeff G.
right now the "second column" of stuff is just "right-of" the stuff left of it. I would like a way to tell it to right justify to the other side of the cell.
Mark M.
(hello, Micalet -- I will be with you shortly!)
Jeff G.
got it. thanks.
that's all I have for today. Thanks again.
Micalet
ok
Mark M.
Jeff: OK
Micalet: do you have a question?
Micalet
Yes
I have a problem when I try to populate a listview with pictures from internet
I have a listview with some textviews and one imageview
I populate the listview with info from a sqlite
in this database i have the url of some pictures
?
Mark M.
off the cuff, I would think you need to ask that of the author of that library
7:55 PM
Mark M.
I have no way of telling you why that library is logging those messages and is having a problem
you'll need the INTERNET permission in your manifest, and of course you'll want to check and confirm that the URLs are actually valid
Micalet
I tried to contact with him, but have no answer
Mark M.
maybe the solution is to switch to a different library
Micalet
if you read the comment in this question, I tried other methods with the same result
Mark M.
I use Picasso mostly, with SmartImageView for the use cases where Picasso does not fit
my Internet chapter has a complete example of using Picasso to load images from URLs into rows of a ListView
and my MapsV2 chapter has a complete example of using Picasso to load images from URLs into info windows
Micalet
ok thank you
Mark M.
EGHDK: back to you
Micalet
I'll take a look
EGHDK
Okay, so this brings me to my main question. I have a method I came up with called fetchContacts() in my ContactManager class. It runs fine on most of my devices... but on devices like the moto g, and say 8k contacts the method takes about 3 seconds to run and it hangs the UI. From what I can see, the GC slows things down, because in logcat it looks like GC gets called like 4 times. I initially just put my fetchContacts() method call in new Thread(new Runnable() @override run(){fetchContacts()}).start(). Then I got the error "Can't create handler inside thread that has not called Looper.prepare()" Now... I have come across this problem before in my code in AsyncTask trying to touch a GUI element. I know that I shouldn't touch GUI elements not in the main thread. But so what is this whole deal with Handler and looper and such. From what I can see in my code, I'm not touching GUI elements.
Mark M.
I have no idea what is in your fetchContacts() method, but it is doing something that is normally done on the main application thread
you know exactly what it is, because it's where the stack trace tells you
whatever that is, ponder whether it is something you really want to be doing in the background
EGHDK
Yeah... well erm. That's what I'm trying to figure out.
Mark M.
there are ways to have a thread with a Looper
and so it's entirely possible that this would be the right solution
but until you determine what it is that is triggering this need, nobody can really help you determine what the right course of action is
EGHDK
I'm trying to figur eout of that message "Can't create handler inside thread..." means "DO THIS ON THE MAIN THREAD"
8:00 PM
EGHDK
figure out if*
Mark M.
it's more that it's expected that the work would be done on the main thread, which already has a Looper
that's not to say the work cannot be done in the background, but it does beg the question of whether that bit of the work *should* be done in the background
EGHDK
This may be stemming from the fact that I don't know what a Looper is.
Or Handler.
Mark M.
did you read the book chapter on threading?
(my book, not your Java book)
EGHDK
Your book? No.
Mark M.
no offense, but that might be a good idea
EGHDK
Alright.
Mark M.
I don't write this stuff just for grins :-)
EGHDK
That goes through Looper and such?
Mark M.
it goes through Handler
and uses of Handler
Looper is part of the underpinnings behind Handler and the work queue that the main application thread uses
EGHDK
I actually am putting off picking your book back up until I read my head first java book, head first design book, and effective java. Then I'm going to pick your book back up. And hopefully its after the big pivot.
But I guess I will read this part since it applies to me now.
Mark M.
yeah, if you're trying to do active development in parallel with reading those things cover-to-cover, it'll be a while before you get back to my book
EGHDK
Again, I understood that most likely my code needs to run on the main thread, but I don't get why the error says Looper.prepare().
Mark M.
well, because that's how they elected to word the error message
don't assume that all error messages are well-written
EGHDK
Heh.
8:05 PM
Mark M.
moreover, I think that the authors of that error message expected it to be infrequently encountered by run-of-the-mill app developers
and more encountered by people who are intentionally messing with funky threading stuff
in reality, it shows up more often than they might have thought
EGHDK
So if my new thread(new Runnable(run fetchContacts()).start() code crashes. Why does it not crash when I put Looper.prepare() right before the fetchContacts() method?
Mark M.
well, first, that'd be the wrong place for it
or, more accurately, it's probably insufficient
just having Looper.prepare() is akin to attempting to fry some chicken with just a frying pan, leaving out the stove, oil, and chicken
the point behind a thread with a Looper is for the Looper to be driving what the thread is doing
a concept that would be vastly easier to explain if you read my chapter on threading for background
EGHDK
Okay, so just putting Looper.prepare() doesn't actually do anything?
Mark M.
not in a way that would really address your problem
EGHDK
Okay, I'll read it tonight. Thanks
Mark M.
Micalet: do you have another question?
Micalet
No. Thats all for the moment
Mark M.
OK
if anyone has another question, go right ahead
Micalet
T'll try one of these libraries
Micalet
has left the room
8:10 PM
EGHDK
Okay, Mark so I set up my contentObserver for seeing when contacts have changed.
Mark M.
OK
EGHDK
It works pretty well. But I was wondering if the contentobserver will be called if my application is in the background... or if my app process is dead.
Mark M.
it will be called while it is registered and your process is running
it will not be called if your app process is dead
because it no longer exists
EGHDK
Okay. So even if my app is in the background but the process is technically running?
Mark M.
it should, so long as the observer is still registered
EGHDK
Got it.
I'm having a problem with GCM.
Mark M.
could you be more specific? :-)
8:15 PM
EGHDK
Basically I have an basic messager app. I create an account "UserA". Then I uninstall the app. Then I install the app again, and create an account "UserB". If someone sends a message to "UserA" the notification now shows up on my phone.
So my problem is unregistering the GCM
I guess.
Mark M.
:: shrug ::
your server should be notified when you attempt to send a message to a GCM ID that has been unregistered
however, that will take some time
if you're trying this test over a matter of minutes, I would not be shocked to see the behavior that you describe
EGHDK
So uninstalling an application "unregisters" the GCM?
Mark M.
it's supposed to -- Play Services detects the uninstall and alerts its GCM servers
EGHDK
Okay, so my next part to this question is now, if I have a button in my app for "logging out and delete all user data" almost like an app reset. I should at this time call unregister()?
Mark M.
off the cuff, that seems reasonable
but, I don't know your app well enough to state that conclusively
8:20 PM
EGHDK
Agreed. Okay, so what if I already have devices that already have this problem? Getting duplicate gcm recievers. So its like this one hardware device has two different GCM ids. Is there any way to push out an update, that will just "unregister all the gcms for this app on this phone"?
Mark M.
not that I am aware of
EGHDK
Basically, since unregister() doesn't take a param... how does it know what to unregister?
Mark M.
but you're the one sending to those GCM IDs
GCM caches the ID in your internal storage IIRC
so it knows the ID
if you want your server to stop sending to those GCM IDs, update your server
the "app unregistered" path is designed to help you detect IDs that are invalid
however, you still are supposed to be updating your server's database to reflect what GCM IDs are (in theory) still outstanding
EGHDK
Hmm... but again if my server has two gcm ids, mapped to one phone. How do I tell it to unregister the correct one?
Mark M.
you can't unregister() the old one
EGHDK
unregister() only unregisters the current gcm id?
Mark M.
AFAIK
8:25 PM
Mark M.
the old one would have been erased when the old app installation was uninstalled
EGHDK
Got it.
I'll look into it more later.
I'm trying to make a sample app that you can choose a movie from your gallery. Once you onActivityResult is valid, you'll be able to trim your video and resave it as a new clip. I don't know where to start with it. What would you recommend?
Mark M.
where to start with what?
choosing the movie?
if so, the chapter on the MediaStore has a sample app demonstrating that
EGHDK
I got the "choosing the movie" part. I'm not sure how to start implementing a trimming mechanism.
Mark M.
are you expert in C/C++ and movie codecs?
EGHDK
no...
8:30 PM
Mark M.
then I'd strongly recommend that you write another app
EGHDK
Hah. It'd be that hard? No easy MediaPlayer trim methods or something...?
Mark M.
no
EGHDK
Alright. Well that solves that.
You go over ndk in your book correct?
Mark M.
and that's a wrap for today's chat
yes, I have an NDK chapter
EGHDK
Okay. Another rabbit hole for another day.
Mark M.
not that big, as I haven't done much C/C++ in ~15 years
EGHDK
Thanks mark.
Mark M.
the transcript will be posted to http://commonsware.com/office-hours/ shortly
the next chat is Thursday at 7:30pm US Eastern Time
have a pleasant day!
EGHDK
has left the room
Jeff G.
has left the room
Mark M.
turned off guest access

Thursday, July 3

 

Office Hours

People in this transcript

  • EGHDK
  • Jeff Gonzales
  • Mark Murphy
  • Micalet