Mark M. | has entered the room |
Oct 25 | 7:25 PM |
Mark M. | turned on guest access |
Ron T. | has entered the room |
Mark M. |
hello, Ron!
|
Mark M. |
how can I help you today?
|
Ron T. |
View paste
(7 more lines)
|
Mark M. |
my impression is that #2 is the scenario: you're not banned, but you cannot update without complying with the targetSdkVersion requirement
|
Mark M. |
and so, AFAIK, with respect to "Will our existing APKs of these apps currently in PLAY continue to be available for download/install after Nov 1?", the answer is "yes"
|
Oct 25 | 7:30 PM |
Mark M. |
that being said, IANAGNDIPOOTV (I am not a Googler, nor do I play one on TV)
|
Mark M. |
I have no special insights, insider knowledge, etc.
|
Ron T. |
Great! That is all I needed for tonight. Many thanks, over and out
|
Mark M. |
OK!
|
Ron T. | has left the room |
Oct 25 | 7:35 PM |
Lucy | has entered the room |
Mark M. |
hello, Lucy!
|
Mark M. |
how can I help you today?
|
Lucy |
Hi Mark, I just logged in to ask a question and realized I might know the answer. I will tell you what it was anyway....
|
Lucy |
When a notification comes in I am using the flags "Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP" when I start the activity in order to have only one at a time.
|
Oct 25 | 7:40 PM |
Aaron | has entered the room |
Lucy |
That is, when a notification comes in I start an activity and I want that to be the only activity running in the app after tapping it open.
|
Mark M. |
you mean, the only activity in the task
|
Mark M. |
(BTW, hello Aaron -- I will be with you shortly!)
|
Lucy |
Oh, yes the only activity in the task.
|
Aaron |
hello, thanks
|
Lucy |
I just tried it and it seems to be working as expected. I was thinking there could be something special about activities launched from tapping a notification but maybe not after all.
|
Mark M. |
I wouldn't say that activities started via a PendingIntent are "special"
|
Mark M. |
they are different than an activity calling startActivity(), in that then we already know a task to work with (the activity's own task), whereas we do not with a PendingIntent
|
Mark M. |
and so some behavior that we take for granted with activities, like each going into the same task, do not necessarily hold in the PendingIntent scenario
|
Lucy |
I see. This is excellent insight for me. I will do some testing to make sure how many activities I have running after opening a few notifications.
|
Lucy |
Thanks Mark!
|
Mark M. |
you're welcome!
|
Oct 25 | 7:45 PM |
Mark M. |
let me take a question from Aaron, and I'll turn back to you in a bit
|
Mark M. |
Aaron: your turn! do you have a question?
|
Lucy |
Sure, I'm all set for now. "See" you soon. :-)
|
Lucy | has left the room |
Aaron |
yes, a few, here they are:
|
Aaron |
View paste
|
Mark M. |
regarding your first bullet, the biggest thing is: putting layout_ attributes in a style is not particularly recommended
|
Aaron |
I see
|
Mark M. |
it works AFAIK, but that's not usually the sort of thing that styles get used for
|
Mark M. |
in terms of the naming system, ¯\_(ツ)_/¯
|
Mark M. |
regarding your second bullet, apply() should not trigger a StrictMode violation -- check LogCat to see what is getting logged (assuming that you also have penaltyLog())
|
Mark M. |
note that the first time that you reference a SharedPreferences in your process, the XML for the saved preferences has to get read, and that *will* trigger a StrictMode violation if done on the main application thread
|
Mark M. |
(and there is no built-in apply() equivalent to address that)
|
Mark M. |
regarding your third bullet, fragments, like activities, services, and a variety of other things, get created using reflection
|
Mark M. |
and they get created automatically, by code that is not yours
|
Mark M. |
in the case of fragments, that occurs on configuration changes, for non-retained fragments
|
Mark M. |
code that is not yours has no good way of knowing how to invoke an arbitrary constructor
|
Oct 25 | 7:50 PM |
Mark M. |
the typical workaround for that is to have some sort of "factory" that creates those objects, so you have more constructor flexibility
|
Mark M. |
Java has a reputation for factories -- a running joke is needing a SomethingFactoryFactoryFactory to get the SomethingFactoryFactory to get the SomethingFactory to make you a Something
|
Mark M. |
so, they probably went the reflection-based zero-argument constructor approach to avoid factories
|
Mark M. |
regarding your last bullet, DI tends to get used for things that you will want to mock in testing
|
Mark M. |
you rarely need to mock a fragment
|
Mark M. |
and, as I covered in the third bullet, Android recreates fragments automatically in some scenarios, which might confuse a DI system
|
Mark M. |
but, for example, repositories are very likely to get injected, for apps that use DI
|
Mark M. |
because for isolated GUI testing, you can easily set up the DI to replace the real repository with a controllable mock, and isolate you from the server that the repository hits
|
Mark M. |
so... what of all that needs clarification? :-)
|
Oct 25 | 7:55 PM |
Aaron |
regarding the styles, do you say "not usually the sort of thing" because styles are intended to be reused on multiple elements and adding layout constraints to specific elements pretty much limits it to being used on a single element?
|
Mark M. |
that's one strong reason, yes
|
Aaron |
what else?
|
Mark M. |
styles are mostly for look-and-feel
|
Mark M. |
positioning isn't really part of that
|
Mark M. |
plus, particularly with ConstraintLayout and RelativeLayout, your layout rules often need to identify particular widget IDs
|
Mark M. |
that's not very reusable, may screw up refactoring, etc.
|
Aaron |
I see, I did this mainly to clear out my XML layout files when I was implementing data binding, so that I could focus on that, but I get your point
|
Mark M. |
moving stuff into styles is fine, just not those sorts of positioning attributes
|
Mark M. |
but, yes, layout files can get wordy
|
Aaron |
got it
|
Oct 25 | 8:00 PM |
Aaron |
about StrictMode, I looked at the logs and I'm just getting android.os.StrictMode$StrictModeDiskReadViolation, so it sounds like that's expected. the flash occurs when I change a setting on my preferences screen, so I guess there is just a read taking place right before the write?
|
Aaron |
but the violation is not actually due to the write
|
Mark M. |
the stack trace should point out where specifically the violation is occuring
|
Mark M. |
can you post the stack trace here?
|
Aaron |
View paste
(32 more lines)
|
Mark M. |
it is coming from your setDefaultValues() call in onCreate() of your MainActivity
|
Aaron |
there are two violations, I think because I have two SharedPrefs, the default, as well as a second prefs file for holding an oAuth token
|
Aaron |
ah
|
Mark M. |
under the covers, that will need to read the XML, and hence you get the violation
|
Aaron |
should I do that in an ASyncTask, or something?
|
Mark M. |
well, that depends on your definition of "should" :-)
|
Mark M. |
in an ideal world, yes, you would move the SharedPreferences stuff to a background thread of one form or another
|
Mark M. |
however, unless you are storing two tons of stuff in your SharedPreferences, this I/O will not be very expensive
|
Mark M. |
and so it is reasonably common for this sort of violation to get ignored
|
Mark M. |
particularly for app startup
|
Oct 25 | 8:05 PM |
Mark M. |
now, if you were hitting the Reddit Web service API on the main application thread, you would deserve to be slapped with a trout
|
Mark M. |
which is why Android has StrictMode configured out of the box for NetworkOnMainThreadException
|
Aaron |
ok got it. yes, I don't recall seeing anything in your book or the official documentation about doing reads off the main thread
|
Mark M. |
all disk I/O should be done on background threads
|
Mark M. |
I don't distinguish between read and writes on this topic much in the book
|
Aaron |
I definitely deserve to be hit with a trout, but not for that particular reason
|
Aaron |
OK, I see
|
Mark M. |
SharedPreferences specifically is a bit odd, in that it offers an asynchronous API for writing but not for reading
|
Mark M. |
but, then again, SharedPreferences is a bit odd in a variety of ways
|
Mark M. |
almost anything from API Level 1 would be considered a bit odd nowadays
|
Aaron |
OK, great, it makes sense
|
Aaron |
let me see if I have anything else
|
Oct 25 | 8:10 PM |
Aaron |
OK I do have one more, this one might be extra dumb as I've not tried to think it through myself yet, but I'm going to ask anyway
|
Aaron |
regarding p.479-80 in BCG
|
Mark M. |
OK
|
Aaron |
that findFragmentById check is a pattern you use frequently in the book
|
Oct 25 | 8:15 PM |
Mark M. |
you mean in the code snippet at the top of 479?
|
Aaron |
yes
|
Aaron |
correct me if I'm wrong here -
|
Aaron |
if you didn't perform that check, and you just unconditionally did the transaction, what would happen is that you would accumulate OtherFragments each time there was a config change, right?
|
Mark M. |
yes
|
Aaron |
OK, so
|
Aaron |
in my app, I am doing this in my MainActivity onCreate
|
Aaron |
View paste
|
Aaron |
similar thing, except instead of searching for the fragment, I am checking the bundle status
|
Aaron |
it seems to produce the same outcome, i.e., preventing an accumulation of fragments
|
Mark M. |
yes
|
Mark M. |
in fact, I used to do it that way
|
Aaron |
but I am not quite sure how it differs functionally from what you are doing
|
Aaron |
oh?
|
Mark M. |
well, in the end, you should get the same results
|
Mark M. |
from an educational standpoint, I felt that it was better to check for the fragment's existence, rather than assume its existence based on the savedInstanceState Bundle's condition
|
Aaron |
ah, ok
|
Mark M. |
from a practical standpoint, what you should have should work
|
Aaron |
well that's good, because I couldn't figure out what would be different between the two, in terms of outcome
|
Aaron |
great
|
Mark M. |
but since you are not using the Bundle in that if() block, checking whether that Bundle is null is therefore relying on side effects
|
Oct 25 | 8:20 PM |
Mark M. |
in the real world, there should be no difference
|
Aaron |
ok great, this reminds me of one other thing I wanted to check: where does an Activity store the state of its fragments during a configuration change? in the savedInstanceState bundle, or somewhere else?
|
Aaron |
I think I asked this once before and forgot to write down the answer.
|
Mark M. |
I was about to say...
|
Aaron |
:X
|
Mark M. |
this is probably a gross simplification, but basically the FragmentManager gets retained across the configuration change
|
Aaron |
I'll find the chat transcript
|
Aaron |
that's all I've got - thanks a lot
|
Mark M. |
you're welcome!
|
Oct 25 | 8:25 PM |
Aaron |
should have this app done(TM) soon(TM)
|
Oct 25 | 8:25 PM |
Mark M. |
hey, I always measure "soon" on geologic time scales, just for that reason
|
Aaron |
yeah... it's been kind of frustrating because the breadth of the tools/features I'm trying to include is so wide, I'm not really getting a chance to learn anything more than superficially, but I feel that the breadth-first approach is going to be the quickest way to snag a first job in this field so I can start getting paid to learn, but we'll see if I was right about that
|
Aaron |
but this app should have pretty much everything, Retrofit, Glide, MVVM architecture, data binding, DI, some unit tests. hopefully it will stand out
|
Mark M. |
I wish you luck with it!
|
Aaron |
I am out, have a good one!
|
Aaron |
thanks!
|
Oct 25 | 8:30 PM |
Mark M. |
the next chat is Saturday at 4pm US Eastern
|
Mark M. |
this chat's transcript will be posted to https://commonsware.com/office-hours/ shortly
|
Mark M. |
have a pleasant day!
|
Aaron | has left the room |
Mark M. | turned off guest access |