Office Hours — Today, October 25

Saturday, October 22

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!
how can I help you today?
Steve S.
I have some follow-up questions to our discussion last Thursday.
Let me upload a question.
View paste (2 more lines)
I have a follow-up question to the discussion we had last Thursday regarding displaying a progress dialog while waiting for a Rest request (made using an IntentService) to complete.

Based on our discussion, I've tried the following approach: (1) use a DialogFragment as a progress indicator, (2) display the indicator in response to appropriate onClick events, and (3) dismiss it in a BroadcastReceiver registered using LocalBroadcastManager when the BroadcastReceiver receives a broadcast from the service indicating the request has completed.

This approach works partially but not completely. 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. This suggests further that there is a race condition when the phone is rotated: the BroadcastReceiver is registered using LocalBroadcastManager in onResume and unregistered in onPause, so there is a (small) interval during which no BroadcastManager is registered, and broadcasts would be missed, when the phone is rotated.

To deal wit
...
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
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)
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
in regards to the latter, greenrobot's EventBus offers sticky events, which can be of use here
Steve S.
i was wondering about that
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
ideally, determining whether you still need the progress dialog would just "fall out" from doing that check
Alesandro
View paste
Hello Mark,

there is no hurry - thanks.
Mark M.
if, for whatever reason, that's impractical, then your flag, or sticky events, or something like that may be of use
4:05 PM
Mark M.
let me take a question from Alesandro, and I'll return to you in a bit
Alesandro: your turn! do you have a question?
Alesandro
Sure
I try track the progress of an HTTP upload.
View paste
I am using plain HttpUrlConnection.
Actually I am on https://github.com/kevinsawicki/http-request but this is just a thing wrapper around it.
*thin wrapper
View paste
Here is the line used to track the upload progress:
https://github.com/kevinsawicki/http-request/blob/master/lib/src/main/java/com/github/kevinsawicki/http/HttpRequest.java#L2611
4:10 PM
Alesandro
View paste
Now to my problem.
This method of keeping track of the upload progress does not work.
If the upload progress takes about 10s the progress callbacks from this part are all called in one or two seconds.

Any idea?
Mark M.
it is possible that is more tied to something with your network, such as an oddly configured proxy server
have you changed bufferSize from its default value of 8192?
Alesandro
I don't think so, I have no proxy server in my environment.
Yes I tweaked the buffer size and called setChunkedStreamingMode.
Mark M.
it is possible that those have an effect on the progress reporting
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
4:15 PM
Mark M.
oh, so, if you leave them alone, you still get the late start to the progress?
(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)
are you saying that the time between the last onUpload() call and when copy() returns is 8s?
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
Not the copy() returning but getting the actual response.
I do have the presumption the server takes a lot of time to response but I have no idea on how to really track down all the parts of a request using HttpUrlConnection.
sure
Mark M.
Alesandro: I am not sure how to help you, but we can talk about this more in a bit
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
partly, that is due to better libraries that are more granular, such as the revamped Play Services SDK
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
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.
View paste
When possible.  And closely evaluate our library use to try to keep it in check.
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
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.
...something big...
Mark M.
for that, the Gradle depenencies report may prove to be illumunating
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
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?
4:30 PM
Mark M.
sure
that's fairly typical
any time the real data resides on disk or the network, you want to be thinking about a cache
and that, in Android, inevitably requires a singleton
(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).
is that right?
Mark M.
not necessarly
er, necessarily
Steve S.
ok
Mark M.
it really depends a lot on your app architecture
the question that the activity has, returning from the background, is "what should I be showing to the user?"
after all, in many apps, the data may have been changed along the way (e.g., periodic work, push messages, SyncAdapter)
somehow, the activity has to get an answer that question
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
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.
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
The only thing which would help me is if you know how to track the different stages of a requests using HttpUrlConnection.
By stages I mean "SSL Handshake", "RequestUpload", "ResponseDownload" and something like that.
Mark M.
no, sorry
that is all inside the framework
and the answer would vary by Android version
HttpUrlConnection was replaced in Android 4.4 with a different implementation
however, the SSL handshake happens first
so, if you are getting data, you are past that point
Alesandro
okhttp is the new implementation as far as i know
but there is no public api to it
Mark M.
a forked OkHttp 1.x, I think
well, you could use OkHttp itself, which is what I usually do
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
er, would go
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.
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
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
let me take questions from the others, and with luck, I will be back with you before the chat is over
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
Steve: your turn! do you have another question?
Alesandro
View paste
I will leave now - thanks!
Cheers Alesandro
Eugene W.
has left the room
Steve S.
yes, another follow-up. i'll paste it in.
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
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?
usually, with a DialogFragment, you call show() once and you call dismiss() once
regardless of configuration changes, because the fragment handles those for you
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
but, the dialog is discarded when the activity goes away
in a configuration change, you are getting rid of the old dialog and getting a brand-new dialog for the new activity
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
suppose we have an instance of an activity -- call it A
A has a DialogFragment (D), which shows a ProgressDialog (P)
now the user rotates the screen
Android creates a new instance of the same activity -- call this instance A'
A' creates a new instance of the DialogFragment (D'), which creates a new instance of the ProgressDialog (P')
A, D, and P are destroyed and garbage-collected
this happens because fragments are automatically destroyed and recreated on a configuration change
rephrase: outstanding fragments, being managed by a FragmentManager, are automatically destroyed and recreated on a configuration change
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
and you would look at that value as a clue as to what you should be doing in the new activity instance
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
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.
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!
:-)
5:00 PM
Mark M.
that's a wrap for today's chat
the transcript will be posted to https://commonsware.com/office-hours/ shortly
the next chat is tomorrow at 7:30pm US Eastern
have a pleasant day!
Steve S.
has left the room
Mark M.
turned off guest access

Saturday, October 22

 

Office Hours

People in this transcript

  • Alesandro
  • Eugene Wisor, Netscout Systems
  • Mark Murphy
  • Steve S