Oct 25 | 3:55 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Steve S. | has entered the room |
Steve S. |
Hi, Mark!
|
Mark M. |
hello, Steve!
|
Mark M. |
how can I help you today?
|
Steve S. |
I have some follow-up questions to our discussion last Thursday.
|
Steve S. |
Let me upload a question.
|
Steve S. |
View paste
(2 more lines)
|
Oct 25 | 4:00 PM |
Mark M. |
OK, give me a bit to read all that...
|
Steve S. |
sure
|
Mark M. |
"For instance, if I press Home while the progress dialog is up and don't return to the app until after the Rest request has completed, the dialog is never dismissed because the broadcast indicating the request has completed isn't received by the LocalBroadcastManager" -- well, the broadcast is only really there for live status updates
|
Steve S. |
right
|
Alesandro | has entered the room |
Mark M. |
you need some other way, upon returning from the background, to determine that the work was completed
|
Mark M. |
if the work was not yet completed, then wait for a broadcast
|
Steve S. |
ok
|
Mark M. |
(BTW, hello, Alesandro -- I will be with you shortly)
|
Mark M. |
so, your flag would be one possible way of doing that, though ideally it would either come more naturally from the way your UI uses whatever the results of the background work are, or you use a different event bus
|
Mark M. |
in regards to the latter, greenrobot's EventBus offers sticky events, which can be of use here
|
Steve S. |
i was wondering about that
|
Steve S. |
i've been reading about it today, and it looks like it could provide a cleaner, more robust approach
|
Mark M. |
you should already have code in your UI for reloading the UI from the backing store when you return from the background
|
Mark M. |
ideally, determining whether you still need the progress dialog would just "fall out" from doing that check
|
Alesandro | |
Mark M. |
if, for whatever reason, that's impractical, then your flag, or sticky events, or something like that may be of use
|
Oct 25 | 4:05 PM |
Mark M. |
let me take a question from Alesandro, and I'll return to you in a bit
|
Mark M. |
Alesandro: your turn! do you have a question?
|
Alesandro |
Sure
|
Alesandro |
I try track the progress of an HTTP upload.
|
Alesandro |
View paste
|
Alesandro |
*thin wrapper
|
Alesandro |
View paste
|
Oct 25 | 4:10 PM |
Alesandro |
View paste
|
Mark M. |
it is possible that is more tied to something with your network, such as an oddly configured proxy server
|
Mark M. |
have you changed bufferSize from its default value of 8192?
|
Alesandro |
I don't think so, I have no proxy server in my environment.
|
Alesandro |
Yes I tweaked the buffer size and called setChunkedStreamingMode.
|
Mark M. |
it is possible that those have an effect on the progress reporting
|
Mark M. |
it might also be something with the specific HTTP request that you are making (e.g., server is generating the response, and that is taking most of your time)
|
Eugene W. | has entered the room |
Alesandro |
oh sorry ... by "tweaked" I mean I have played with these settings but nothing has changed when it comes to the progress reporting
|
Oct 25 | 4:15 PM |
Mark M. |
oh, so, if you leave them alone, you still get the late start to the progress?
|
Mark M. |
(BTW, hello, Eugene -- I will be with you shortly!)
|
Eugene W. |
Hi Mark and others.
|
Alesandro |
sorry mark I didn't get this question
|
Mark M. |
Alesandro: if you do not change the bufferSize, you still experience your problem with the progress?
|
Alesandro |
yes
|
Mark M. |
you might try using your URL for the download in some other code, such as my OkHttp-based progress sample: https://github.com/commonsguy/cw-omnibus/tree/m...
|
Alesandro |
the progress callback is always called with values from 0 to 100 but after 100 was returned the request does take another 8s
|
Mark M. |
oh, I misunderstood -- I thought the delay was in the beginning (8 seconds of nothing, then 2 seconds of progress)
|
Mark M. |
are you saying that the time between the last onUpload() call and when copy() returns is 8s?
|
Oct 25 | 4:20 PM |
Mark M. |
Alesandro: let me take questions from the others, and we can continue on this in a little while
|
Alesandro |
View paste
|
Alesandro |
sure
|
Mark M. |
Alesandro: I am not sure how to help you, but we can talk about this more in a bit
|
Mark M. |
Eugene: your turn! do you have a question?
|
Eugene W. |
Mark, we are early in development on our Android application, mostly a prototype at this point. However, we already reached the 64K Dalvik Executable method reference limit (see https://developer.android.com/studio/build/mult...). We did increase the limit using multidex. We have included a number of 3rd party libraries and that may be the root cause. It is possible we could end up doubling or even tripling the default initial 64K limit. However, I'm curious for your thoughts on this. Is it common now to exceed this limit? Are there side effects we should be watching out for?
|
Mark M. |
I would describe it as uncommon, insofar as I do not think most developers hit it
|
Mark M. |
partly, that is due to better libraries that are more granular, such as the revamped Play Services SDK
|
Mark M. |
now, with the size of the Android developer community, "uncommon" is still a whole lot of people :-)
|
Eugene W. |
Perhaps we are not utilizing libraries that have granular options.
|
Mark M. |
I have not had to deal with multidex personally, and so other than longer build times and perhaps some Instant Run challenges, I do not have any particular side effects to warn about, for the native multidex
|
Oct 25 | 4:25 PM |
Mark M. |
is your minSdkVersion 21 or higher?
|
Eugene W. |
Yes we are currently at 23
|
Mark M. |
OK, so you will not need the support multidex backport, which introduces some security issues
|
Eugene W. |
I'll make sure we capitalize on granular libraries.
|
Mark M. |
yeah, libraries like Guava, that are "kitchen sink" libraries, tend to be problems
|
Eugene W. | |
Mark M. |
IMHO, multidex is something to be used as a stop-gap while trying to figure out what to do to trim matters back
|
Mark M. |
the APK Analyzer in Android Studio 2.2 can help you determine what methods you are referencing
|
Eugene W. |
Thanks for the feedback Mark. Perhaps we are inadvertently including something bug that is not needed.
|
Eugene W. |
...something big...
|
Mark M. |
for that, the Gradle depenencies report may prove to be illumunating
|
Mark M. |
it helps you visualize all the transitive dependencies that you are pulling in
|
Eugene W. |
OK, thanks Mark.
|
Mark M. |
let me swing back to the others, and I'll return to you in a bit
|
Mark M. |
Steve: back to you! do you have another question?
|
Steve S. |
you suggested a backing store for the UI - that could be a singleton cache?
|
Oct 25 | 4:30 PM |
Mark M. |
sure
|
Mark M. |
that's fairly typical
|
Mark M. |
any time the real data resides on disk or the network, you want to be thinking about a cache
|
Mark M. |
and that, in Android, inevitably requires a singleton
|
Mark M. |
(a carefully written singleton)
|
Steve S. |
ok. but there's still the issue with missing broadcasts from the IntentService when no LocalBroadcastManager is registered. it sounds like looking into GreenRobot event bus with sticky events would help with that (and would also finesse the need for caching the state of the progress dialog).
|
Steve S. |
is that right?
|
Mark M. |
not necessarly
|
Mark M. |
er, necessarily
|
Steve S. |
ok
|
Mark M. |
it really depends a lot on your app architecture
|
Mark M. |
the question that the activity has, returning from the background, is "what should I be showing to the user?"
|
Mark M. |
after all, in many apps, the data may have been changed along the way (e.g., periodic work, push messages, SyncAdapter)
|
Mark M. |
somehow, the activity has to get an answer that question
|
Mark M. |
if the answer to that question is "here's what we have, and, by the way, we are in the middle of an update", you show the dialog
|
Mark M. |
if the answer to that question is "here's what we have, and we're stable", you don't show the dialog
|
Steve S. |
the only thing i need to keep track of would be the progress indicator. and i was thinking could figure out whether to display that via a sticky event.
|
Mark M. |
that can work
|
Steve S. |
ok. i'll try that out.
|
Oct 25 | 4:35 PM |
Mark M. |
let me return to the others, and I'll be back with you in a bit
|
Steve S. |
sure
|
Mark M. |
Alesandro: your turn! do you have a follow-up question?
|
Alesandro |
View paste
|
Mark M. |
no, sorry
|
Mark M. |
that is all inside the framework
|
Mark M. |
and the answer would vary by Android version
|
Mark M. |
HttpUrlConnection was replaced in Android 4.4 with a different implementation
|
Mark M. |
however, the SSL handshake happens first
|
Mark M. |
so, if you are getting data, you are past that point
|
Alesandro |
okhttp is the new implementation as far as i know
|
Alesandro |
but there is no public api to it
|
Mark M. |
a forked OkHttp 1.x, I think
|
Mark M. |
well, you could use OkHttp itself, which is what I usually do
|
Oct 25 | 4:40 PM |
Mark M. |
with respect to your current library, if copy() returns, I would think that the download is done, and I do not know where the other 8s would
|
Mark M. |
er, would go
|
Mark M. |
if you can reproduce the problem with some public URL, you might create a sample app and ask the library author
|
Alesandro |
I could but I am writing a library which should have zero dependencies thats why I am stuck with it.
|
Mark M. |
I thought https://github.com/kevinsawicki/http-request was a dependency
|
Alesandro |
It is just one class which I copied into my library because plain HttpUrlConnection is not easy to use but adding whole OkHttp would be too much I think.
|
Mark M. |
make sure you refactor that class and put it in your own package, or at least not the original package
|
Mark M. |
otherwise, if a developer wants to use your library *and* another version (e.g., newer one) of this library, the developer will not be able to
|
Alesandro |
I will try - thanks
|
Mark M. |
I am sorry that I could not be of greater help to you
|
Mark M. |
let me take questions from the others, and with luck, I will be back with you before the chat is over
|
Mark M. |
Eugene: back to you! do you have another question?
|
Alesandro |
no problem it is a very special topic and not that much android related
|
Eugene W. |
No, I think I'm good for now, thanks again!
|
Mark M. |
OK
|
Mark M. |
Steve: your turn! do you have another question?
|
Alesandro | |
Eugene W. | has left the room |
Steve S. |
yes, another follow-up. i'll paste it in.
|
Steve S. |
A second follow-up question has to do with how I've implemented the DialogFragment. I'm creating a ProgressDialog in onCreateDialog in my DialogFragment subclass. This stores a reference to the activity, so I want to make sure I'm not leaking memory. Can I avoid a memory leak by checking if an instance of the DialogFragment is already running (via FragmentManager#findFragmentByTag) to determine whether to call show (something I should be presumably be doing anyway)?
|
Alesandro | has left the room |
Oct 25 | 4:45 PM |
Mark M. |
OK, I'm confused
|
Steve S. |
ok
|
Mark M. |
your last sentence ("Can I avoid...") -- in what circumstances are you looking to do this?
|
Mark M. |
usually, with a DialogFragment, you call show() once and you call dismiss() once
|
Mark M. |
regardless of configuration changes, because the fragment handles those for you
|
Oct 25 | 4:50 PM |
Steve S. |
so there's no issue about memory leaks with using ProgressDialog for a DialogFragment even though the ProgressDialog stores a reference to an activity?
|
Mark M. |
all dialogs have a reference to their activity
|
Mark M. |
but, the dialog is discarded when the activity goes away
|
Mark M. |
in a configuration change, you are getting rid of the old dialog and getting a brand-new dialog for the new activity
|
Mark M. |
that's all handled for you by DialogFragment, which is the reason why it's a common solution, assuming that you're willing to use fragments
|
Steve S. |
i see. so the DialogFragment replaces the reference to the activity on a configuration change?
|
Mark M. |
no, the DialogFragment creates a fresh dialog
|
Mark M. |
suppose we have an instance of an activity -- call it A
|
Mark M. |
A has a DialogFragment (D), which shows a ProgressDialog (P)
|
Mark M. |
now the user rotates the screen
|
Mark M. |
Android creates a new instance of the same activity -- call this instance A'
|
Mark M. |
A' creates a new instance of the DialogFragment (D'), which creates a new instance of the ProgressDialog (P')
|
Mark M. |
A, D, and P are destroyed and garbage-collected
|
Mark M. |
this happens because fragments are automatically destroyed and recreated on a configuration change
|
Mark M. |
rephrase: outstanding fragments, being managed by a FragmentManager, are automatically destroyed and recreated on a configuration change
|
Oct 25 | 4:55 PM |
Mark M. |
if you did not want the DialogFragment -- for example, you are trying to avoid fragments -- you would wind up putting your own value in the saved instance state Bundle to tell you whether you had a dialog going in the old activity instance
|
Mark M. |
and you would look at that value as a clue as to what you should be doing in the new activity instance
|
Mark M. |
but then you would have to take proactive steps to show the dialog again, should that value (and external conditions) indicate that you need to keep showing the dialog
|
Mark M. |
if you are using a DialogFragment, it's the reverse: you need to take proactive steps, in the form of calling dismiss(), when you know that you no longer need the dialog
|
Steve S. |
thanks. that's very clear and helpful.
|
Steve S. |
i appreciate your help! have a good rest of the day, Mark.
|
Mark M. |
you too!
|
Steve S. | has left the room |
Steve S. | has entered the room |
Mark M. |
welcome back!
|
Mark M. |
:-)
|
Oct 25 | 5:00 PM |
Mark M. |
that's a wrap for today's chat
|
Mark M. |
the transcript will be posted to https://commonsware.com/office-hours/ shortly
|
Mark M. |
the next chat is tomorrow at 7:30pm US Eastern
|
Mark M. |
have a pleasant day!
|
Steve S. | has left the room |
Mark M. | turned off guest access |