Sep 19 | 3:55 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Jeffrey | has entered the room |
Mark M. |
hello, Jeffrey!
|
Mark M. |
how can I help you today?
|
Jeffrey |
View paste
|
Jeffrey | |
Sep 19 | 4:00 PM |
Mark M. |
well, indicating a selection in a nav drawer is no different than indicating a selection in any other ListView
|
Mark M. |
I'd use the activated state, not a selector
|
Mark M. |
this is built into ListView
|
MyWay | has entered the room |
Jeffrey |
do you have any example in your book so that I can read it ?
|
Mark M. |
though you can change the color by setting your own StateListDrawable
|
MyWay |
Hi all
|
Mark M. |
of the activated state? it's in the chapter on the nav drawer
|
Jeffrey |
Hi My way
|
Mark M. |
(BTW, hello, MyWay -- I will be with you shortly!)
|
Mark M. |
Jeffrey: I use the activated state a few other places
|
Mark M. |
in terms of maintaining that across configuration changes, that too is no different than just about anything else: use the saved instance state Bundle
|
Mark M. |
so, in onSaveInstanceState(), make a note of what the activated row is (if any)
|
Mark M. |
and in onRestoreInstanceState(), mark it as activated after setting up your ListAdapter for your fresh activity instance with its fresh nav drawer
|
Mark M. |
let me take a question from MyWay, and I will be back with you in a bit
|
Mark M. |
MyWay: your turn! do you have a question?
|
Jeffrey |
ok
|
MyWay |
(Always about the IRC client!), even if I'm checking if the client is connected, it can happen that between a user send a message and when it's sended the client is not connected anymore, in which case I'm getting an exception (RuntimeException: IO exception when sending line to server). My question is about usability... what do you think I should do, Mark?
|
Sep 19 | 4:05 PM |
Mark M. |
well, off the cuff, that particular exception shouldn't be that much different than if the connection is dropped between messages, right?
|
Mark M. |
you might do something in the UI to reflect the fact that the sent message may or may not have made it
|
MyWay |
yes, but this message is lost and the user does not know if it's sent or not
|
Mark M. |
icon, background color, something like that as an indicator on that particular message, perhaps
|
Mark M. |
I don't know enough about your UI to offer much concrete advice
|
MyWay |
should I place an icon to re-send it?
|
Mark M. |
well, they can't re-send it until they are connected again
|
MyWay |
yes, exactly
|
Mark M. |
and depending on the cause of the disconnect, that might be a while
|
MyWay |
so it's better to say: ehy, your message has been lost...
|
Mark M. |
so IMHO the "message may not have made it" indicator needs to be there, without necessarily it being implied that they can somehow re-send it right away
|
MyWay |
yes, thank you
|
Mark M. |
well, I'd use weasel words and go with "may"
|
MyWay |
yes, better
|
MyWay |
and... you'd use a snackbar for it, or?
|
Mark M. |
I don't know the on-the-wire IRC protocol, so I don't know if you can determine even after reconnecting if the message made it
|
Mark M. |
snackbar is not a bad idea
|
Mark M. |
at least at the point of reconnect
|
Mark M. |
so you can have a "RESEND" action on there
|
MyWay |
ok, thank you
|
Mark M. |
how you indicate that the connection was lost overall would be however you doing that anywhere else
|
Mark M. |
and an icon or something on the actual message(s) that didn't make it would be good, so when the snackbar appears, they know what they are resending
|
Mark M. |
but, again, GUI design on the fly in a chat room setting like this is very off the cuff
|
MyWay |
eheh, true
|
Mark M. |
so, imagine a grain of salt, about a foot on a side, and take that grain of salt with any recommendations :-)
|
Sep 19 | 4:10 PM |
MyWay |
^^
|
Mark M. |
let me switch back to Jeffrey, and I'll return to you in a bit
|
Mark M. |
Jeffrey: your turn! do you have another question?
|
Jeffrey |
Thanks Mark. I have no other questions today.
|
Mark M. |
OK -- if you come up with one while you're still here, let me know, so I can swing back to you
|
Mark M. |
MyWay: over to you!
|
MyWay |
eheh, same, no questions anymore :P
|
Mark M. |
OK, well, if either of you come up with one, chime in!
|
MyWay |
anyway good idea to add a saturday day
|
Mark M. |
yeah, it's one of those "why didn't I think of that years ago?" sorts of things...
|
MyWay |
ahah
|
Sep 19 | 4:15 PM |
MyWay |
ah, do you think on version 6.9 there will be something on the account manager? :P
|
Mark M. |
no, there won't
|
MyWay |
oh :(
|
Mark M. |
that's a "no time real soon" topic
|
MyWay |
on IRC clients that I remember of, I've always seen plain text, but I don't like it at all
|
MyWay |
even if it's not that sensible data, it's always an account
|
Mark M. |
now, it's possible that some of my concerns with AccountManager -- namely, the awful permissions -- are better in Android 6.0 as part of the permission overhaul
|
Mark M. |
but I'll focus first on other secure storage (e.g., KeyStore), that's more flexible
|
Mark M. |
and get to AccountManager sometime after that
|
MyWay |
ah
|
MyWay |
nice
|
Mark M. |
2016, perhaps, though had you asked me about AccountManager coverage in year X, my answer would be "X+1, perhaps", for the past few years
|
MyWay |
eheh
|
Mark M. |
there's just *so* much to cover in Android...
|
MyWay |
yes, true
|
Sep 19 | 4:20 PM |
MyWay |
ah, about ArrayPagerAdapter, last time I've overriden add() to cache the position of the descriptor
|
MyWay |
now, for some reason, I've received an exception from the playstore saying that I was outofbounds
|
MyWay |
but... a new descriptor can be added only by add(), right?
|
MyWay |
so I thought the exception was raised by the add of my arraylist or something
|
Mark M. |
there's also insert()
|
Mark M. |
plus remove() and move() will impact positions
|
MyWay |
but if I'm not using it (even if I should override them all for future reasons) they're not called, right?
|
Mark M. |
they shouldn't be
|
Mark M. |
I don't believe that I use them for configuration changes and such
|
MyWay |
thanks again
|
Mark M. |
happy to help!
|
Sep 19 | 4:25 PM |
Jeffrey |
Hi guys, I have to leave the room. Happy Saturday!
|
Jeffrey | has left the room |
MyWay |
you too, thanks
|
Sep 19 | 4:30 PM |
MyWay |
bye Mark, have a good Saturday!
|
Mark M. |
you too!
|
MyWay |
Thank you.
|
Sep 19 | 4:35 PM |
EGHDK | has entered the room |
EGHDK |
Hello!
|
Mark M. |
hello, EGHDK!
|
Mark M. |
how can I help you today?
|
EGHDK |
Two threading/memory leak questions from me today. First, I want to make a network request without using an asynctask or a service. I want to start it from an activity, lets say downloading a file/image that I want to display. I don't want to create a service because I only want it for that single activity. The thing is, I don't want to fight the activity lifecycle too much. aka, on rotation I still want it to download. I know you can use a gui-less fragment, but someone on irc said that you can just create a thread in another class to do this for you.
|
Mark M. |
I'd just use an image loading library
|
Mark M. |
there's only a million of 'em
|
EGHDK |
Yes, but if I wanted to do it myself. If I wasn't talking about images per se.
|
Mark M. | |
EGHDK |
Would a thread be fine?
|
Mark M. |
sure
|
EGHDK |
Wouldn't a thread hold a reference to the class/activity that started them?
|
EGHDK |
cause a mem leak?
|
Mark M. |
just don't do that
|
Sep 19 | 4:40 PM |
Mark M. |
create a regular Java class that extends thread, in its own Java file
|
Mark M. |
or, use a static class, if you want to keep the code in the activity
|
Mark M. |
only regular inner classes have the reference to the outer class and trigger a leak
|
EGHDK |
static inner classes do not.
|
EGHDK |
Gotcha.
|
Mark M. |
now, because the thread won't have a reference to the activity, you'll need to use an event bus or something to let the activity know that the work is completed
|
Mark M. |
correct
|
EGHDK |
Okay. So why do you recommend creating a regular java class that extends thread. That won't cause a leak?
|
Mark M. |
static class ~= regular Java class
|
Mark M. |
it's just a bit of "syntactic sugar"
|
Mark M. |
they are basically equivalent
|
EGHDK |
yeah, I understood that also.
|
EGHDK |
But lets say I did want to go the route of a new java class.
|
EGHDK |
Can an object just live without an activity, if the activity told it to start up and run?
|
Mark M. |
well, sure
|
Mark M. |
the risk in general is garbage collection
|
EGHDK |
hmm... without causing a mem leak?
|
Mark M. |
but threads are effectively global in scope
|
Mark M. |
well, the thread itself is a "memory leak"
|
EGHDK |
hmm... Interesting.
|
Mark M. |
anything that the thread holds on to cannot be garbage-collected while the thread is running
|
Mark M. |
that's where the inner class problem gets you, as the thread has an implicit reference to the outer class
|
Mark M. |
you don't have an implicit reference to anything from a static class or a regular Java class
|
EGHDK |
So if I just created a thread inside of the activity on an onClick of a button, that could be a leak to the activity... but If I create a new class, I can have the onClick create and start the thread, but it wouldn't be attached to my activity? (unless I explicitly pass one in or something)
|
Mark M. |
correct
|
Mark M. |
no different than if you create an ArrayList, or a Restaurant
|
Mark M. |
they too do not intrinsically know anything about an activity
|
Sep 19 | 4:45 PM |
EGHDK |
Gotcha. But if I created an ArrayList onCreate, rotated the phone, I wouldn't have one ArrayList...?
|
EGHDK |
Or should I say... the same ArrayList
|
Mark M. |
no
|
Mark M. |
at least, not if your activity is going through the normal destroy-and-recreate cycle
|
Mark M. |
or your fragment is going through the normal destroy-and-recreate cycle, if your onCreate() is in a fragment
|
EGHDK |
You lost me at "no different than if you create an ArrayList, or a Restaurant". Wouldn't they have to be statics to stay around in memory
|
Mark M. |
correct
|
Mark M. |
which is why they *won't* stay around in memory
|
Mark M. |
"stay around in memory" == "memory leak"
|
EGHDK |
Gotcha. So thread is inherently a memory leak... basically.
|
Mark M. |
correct
|
Mark M. |
technically, a thread is a garbage-collection root
|
EGHDK |
So I just have to make sure that it finishes up in an activity (or stop it, or cancel it in onDestroy)?
|
Mark M. |
or let it run to completion, assuming it will complete in a reasonable time
|
Mark M. |
particularly if the work is still needed
|
EGHDK |
Gotcha. Okay. I think that makes sense.
|
EGHDK |
So in an activity, creating a long running asynctask, long running thread, are high risks for mem leaks.
|
EGHDK |
Is that a fair statement?
|
Mark M. |
um
|
EGHDK |
Because of rotation and such
|
Mark M. |
from that standpoint, yes
|
EGHDK |
Last thing for thiss "first" question. Are Listeners and recievers a possible source of mem leaks? Is that a fair statement?
|
Sep 19 | 4:50 PM |
EGHDK |
In onDestroy or onStop I should try to unregister, or stop listening?
|
MyWay | has left the room |
Mark M. |
a BroadcastReceiver registered in the manifest is not itself leaked
|
EGHDK |
gotcha.
|
Mark M. |
a BroadcastReceiver registered via registerReceiver() may get unregistered automatically when the component that registered it is destroyed
|
Mark M. |
but it's good form to unregister it yourself
|
EGHDK |
I guess, I just want to make sure If I implement any callbacks, that they aren't leaked.
|
Mark M. |
and I can't rule out a leak there, if your BroadcastReceiver is an inner class
|
Mark M. |
whether a listener will be a leak depends on what it is attached to
|
Mark M. |
so, an OnClickListener on a Button will not be a leak
|
EGHDK |
Like... onClicksListeners could be a leak no? Why don't they cause leaks...?
|
EGHDK |
Read my mind.
|
Mark M. |
because the Button will be eligible for garbage collection as soon as the Activity is
|
Mark M. |
and the OnClickListener will then be eligible for garbage collection
|
Mark M. |
and the whole thing goes down the drain
|
EGHDK |
Does onDestroy do any kind of unregistering for my views in the super method?
|
Mark M. |
not AFAIK, because it is not needed
|
EGHDK |
I thought the point was that it won't be eligible for GC because it still has a listener.
|
EGHDK |
Hm. Interesting. I'll try to look into that.
|
Mark M. |
your activity, button, listener on the button, and such form an "object graph"
|
Mark M. |
they reference each other
|
Mark M. |
once nothing *outside* the graph has a reference to anything that is part of the graph, the whole graph can be garbage-collected
|
Mark M. |
so, once the activity is destroyed, assuming you didn't screw up and hold a reference to the activity from something else (e.g., a thread), the activity and its widgets and their listeners can all get garbage-collected
|
Mark M. |
now, listeners that are registered on system-level things become more of a problem
|
EGHDK |
Okay, cool. I think I get it. Thanks. "Second" question. I have a service called ApiCalls extends IntentService. I am using retrofit (not sure if your familiar with it). Anyway, I like how intentservice gives me a sort of queue. If I call the synchronous network call in retrofit, the call completes, then the service is destroyed... if I do the async network call, then the service onDestory is called before the network request finishes. Did I just create a mem leak with an asynccall in an IntentService?
|
Sep 19 | 4:55 PM |
Mark M. |
I don't really know
|
Mark M. |
doing something asynchronous from within an IntentService is a serious code smell, so I don't do it
|
EGHDK |
Would it make sense to only call synchronous methods in an IntentService?
|
Mark M. |
yes
|
Mark M. |
you are already on a background thread, anyway
|
Mark M. |
you don't need another background thread
|
EGHDK |
Okay. That makes sense to me. I kind of just wanted another opinion.
|
EGHDK |
Okay, so the next question is subjective I guess, but again just want to run it by you. I have an intent service that takes all network calls. The network call receives data and does the proper modification in the database. Adds, modifies, deletes stuff. The database then (via eventbus) lets whoever wants to know (actvitiy most likely) that the data has changed, and it can choose to update its view if it wants. I think it's a pretty clean app architecture. But I'm not that familiar yet with architecture. Does that sound reasonable to you?
|
Mark M. |
off the cuff, I like it
|
Sep 19 | 5:00 PM |
EGHDK |
Hooray. I mostly came up with it myself. Then started reading about it, and other people seem to do that. But I was pretty proud of myself. It leaves my code with up to date data, don't have to worry about activity lifecycle too much, and I'm not doing any kind of network callbacks in my activities.
|
Mark M. |
right
|
EGHDK |
Which also means no database logic stuff in my activities.
|
EGHDK |
Makes everything pretty clean.
|
Mark M. |
and that's a wrap for today's chat
|
Mark M. |
next one is Tuesday, also at 4pm US Eastern
|
EGHDK |
But I'm trying to see if theres any flaw in it. From a more advanced persons point of view.
|
EGHDK |
Okay Cool. Thanks for doing a Saturday chat
|
EGHDK |
I don't know if you do those often, but it worked for me. Thanks!
|
Mark M. |
as I told others earlier, it's one of those things that I'm embarrassed it took me this long to add
|
Mark M. |
there will be one roughly every other week
|
EGHDK |
Is there a donate button?
|
EGHDK |
on your site somewhere?
|
EGHDK | |
Mark M. |
the Warescription is it
|
EGHDK |
sorry. "warecription"
|
Mark M. |
your Warescription appears to be good until early January
|
Mark M. |
anyway, have a pleasant weekend!
|
EGHDK |
Okay. thanks see ya mark
|
EGHDK | has left the room |
Mark M. | turned off guest access |