Mar 17 | 3:50 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Mar 17 | 4:00 PM |
Guido | has entered the room |
Mark M. |
hello, Guido!
|
Mark M. |
how can I help you today?
|
Guido |
Hi Mark
|
Guido |
I've got a question ready
|
Guido |
View paste
|
Guido |
I didn't realise of this problem until I changed my device orientation again, as my custom onSaveInstanceState was trying to save the state of its view, which didn't exist. So I have to consider two cases depending on whether or not the view exists, which depends on multiple configuration changes. Does this make sense or did I miss anything?
|
Mark M. |
wow, you type fast :-)
|
Guido |
hahah :-)
|
Mark M. |
"however only FragmentB will go through the view creation, FragmentA will not - as it's not visible I guess- is this expected?" -- I haven't specifically looked at this scenario, but I do not find this behavior to be surprising
|
Mark M. |
Android often lazy-creates stuff
|
Mark M. |
in the hopes that perhaps the work will never be needed, saving CPU time, battery, etc.
|
Mark M. |
but, yes, it would imply that a custom onSaveInstanceState() at the fragment level would need to confirm that you indeed have widgets
|
Mark M. |
otherwise, recycle the same state that you got previously, I guess
|
Mar 17 | 4:05 PM |
Guido |
well the status goes lost because when the view doesn't get created I cannot save it so the next time the fragment come back from the backstack bundle is empty
|
Guido |
which doesn't reallymatter as I use it to save the selected items and I would lose them anyway if I close the fragment
|
Mark M. |
you should be able to cache the Bundle itself
|
Mark M. |
you would get it in places like onActivityCreated()
|
Mark M. |
and onCreate()
|
Mark M. |
then, in onSaveInstanceState(), if you do not have your widgets, copy the state out of the cached Bundle instead
|
Jan | has entered the room |
Jan |
Hello...
|
Mark M. |
hello, Jan!
|
Guido |
I forgot the details as I looked into it two weeks ago
|
Mark M. |
Guido: let me take a question from Jan, and I will be back with you in a bit
|
Guido |
but I'll look again into it
|
Mark M. |
Jan: your turn! do you have a question?
|
Guido |
sure
|
Jan |
View paste
|
Mar 17 | 4:10 PM |
Mark M. |
I never see anyone use getBaseContext()
|
Mark M. |
I don't even recall what that returns off the top of my head
|
Mark M. |
with regards when to use what sort of Context, generally speaking, use the one you have
|
Mark M. |
if you are in an Activity or Fragment, use the Activity, for example
|
Mark M. |
the Application object is a singleton Context, which can be useful and can be dangerous
|
Mark M. |
in particular, it knows nothing about themes
|
Mark M. |
and so setting up UI using Application invariably means default styling, not your custom colors, etc.
|
Mark M. | |
Mark M. |
that link is to Dave Smith's epic post, "Context? What Context?"
|
Mark M. |
I point everybody to it for a concise summary of when to use what Context
|
Jan |
I found a sample on internet from someone who seems to be rather advanced in Android and he is using getBaseContext all the time in the sample..... I guess i should ask him why.
|
Jan |
This is the sample : https://github.com/Udinic/AccountAuthenticator
|
Mark M. |
getBaseContext() is undocumented
|
Mark M. |
which means unless you're rooting through the source code, you don't know what it does
|
Jan |
That's the problem :-)
|
Mark M. |
and it means that the rules of what it does can change without warning
|
Raghavendra M. | has entered the room |
Mark M. |
there are probably some specialized scenarios where getBaseContext() is useful
|
Mar 17 | 4:15 PM |
Raghavendra M. |
HI
|
Mark M. |
however, I consider its use to be a code smell, just as I consider the indiscriminate use of getApplicationContext() to be a code smell
|
Mark M. |
(hello, Raghavendra -- I will be with you shortly!)
|
Raghavendra M. |
Sure
|
Jan |
I'll start by having a look at the article you gave me....
|
Mark M. |
Jan: too often, newcomers to Android are newcomers to Java, and therefore do not know about MainActivity.this syntax
|
Mark M. |
so they call getApplicationContext() or getBaseContext(), perhaps based on IDE suggestions
|
Jan |
Is that the way you want to refer to the context of the above lying activity
|
Mark M. |
if you are in a nested class, like an anonymous inner class, MainActivity.this will get you the "outer" class instance
|
Mark M. |
so if you are doing button.setOnClickListener(new View.OnClickListener() { ... });, and you need a Context inside onClick(), you would use YourActivityClassName.this
|
Mark M. |
(where YourActivityClassName is, um, your activity class name :-)
|
Mark M. |
let me take questions from the others, and I will be back with you shortly
|
Mark M. |
Raghavendra: your turn! do you have a question?
|
Jan |
I didn't know that getApplicationContext was not aware of themes ....
|
Raghavendra M. |
yeah
|
Raghavendra M. |
View paste
|
Mark M. |
um
|
Mark M. |
well
|
Mark M. |
Base64 encoding has nothing to do with showing an incremental progress bar
|
Raghavendra M. |
ok
|
Mark M. |
Base64 encoding has nothing to do with queued uploads and downloads of content
|
Raghavendra M. |
it will based on the outputstream
|
Mark M. |
in both cases, whether the content is encoded in Base64 or something else is your choice, between you and the server
|
Mar 17 | 4:20 PM |
Raghavendra M. |
yes
|
Mark M. |
now, when you say "queue upload and download", is the queue just in memory, or are you looking for some sort of a persistent work queue?
|
Raghavendra M. |
in memory
|
Raghavendra M. |
no storing
|
Raghavendra M. |
of the content
|
Raghavendra M. |
as long the app lives
|
Mark M. |
if you only need to do one upload/download at a time, IntentService has a built-in work queue
|
Raghavendra M. |
ok
|
Mark M. |
if you want to do parallel uploads/downloads, create a service with a ThreadPoolExecutor backed by a LinkedBlockingQueue (or PriorityQueue)
|
Raghavendra M. |
how to know which request is currently executing
|
Raghavendra M. |
nth request
|
Raghavendra M. |
i was reading about Tape square library
|
Mark M. |
assign each job a number
|
Raghavendra M. |
ok
|
Mark M. |
if you wanted a persistent work queue, I would steer you to Tape
|
Raghavendra M. |
ok
|
Mark M. |
with regards to the incremental progress bar, you have two pieces to consider: knowing the progress, and communicating that to the user
|
Raghavendra M. |
yes
|
Raghavendra M. |
from a callback
|
Raghavendra M. |
from intent service
|
Mark M. |
you'll need to look for an HTTP client library that gives you convenient access to the progress
|
Raghavendra M. |
or broadcast reciever
|
Mark M. |
(assuming these uploads/downloads are over HTTP)
|
Raghavendra M. |
yes they are on http
|
Mark M. |
I haven't looked into tracking progress, and so I cannot make any recommendations there
|
Raghavendra M. |
ok
|
Mark M. |
then, I'd use an event bus to let your UI layer know about the progress changes
|
Mark M. |
if relevant, you could have a fallback of updating a progress bar in a Notification
|
Raghavendra M. |
ok
|
Mar 17 | 4:25 PM |
Mark M. |
I have a chapter in the book on event bus implementations that demonstrates the fallback concept
|
Raghavendra M. |
ok
|
Raghavendra M. |
will refer to it
|
Raghavendra M. |
how to query the intent service and get the job number
|
Raghavendra M. |
associated with request
|
Mark M. |
I wouldn't do that
|
Raghavendra M. |
ok
|
Mark M. |
I would have the UI layer pick up the job number as part of the progress events
|
Raghavendra M. |
i would use event bus for it
|
Mark M. |
right
|
Raghavendra M. |
event bus again will have dependecies,...?
|
Mark M. |
all are from libraries
|
Raghavendra M. |
its a standalone lib..?
|
Raghavendra M. |
please tell me the chapter name
|
Mark M. |
whether that is LocalBroadcastManager in the Android Support package or libraries that you get from greenrobot, Square, etc.
|
Raghavendra M. |
i have the book downloaded
|
Mark M. |
the concept of event buses is introduced in the "Dealing with Threads" chapter
|
Mark M. |
and there is an "Event Bus Alternatives" chapter later in the book
|
Raghavendra M. |
sure thank you
|
Raghavendra M. |
will refer to it
|
Mark M. |
let me take questions from the others, and I will be back with you
|
Raghavendra M. |
sure
|
Mark M. |
Guido: your turn! do you have another question?
|
Guido |
yes please
|
Guido |
View paste
|
Mark M. |
well, I'd recommend switching to RecyclerView
|
Mark M. |
there are multiple libraries that offer drag-and-drop IIRC
|
Mark M. |
that use RecyclerView for the underlying implementation
|
Mark M. |
and RecyclerView is *way* more suited to that than is ListView
|
Mark M. |
that being said, you can't really drag-and-drop a Cursor, as Cursors are immutable
|
Mar 17 | 4:30 PM |
Mark M. |
at best, you would have to keep track of what position in the list corresponds to what position in the Cursor, as after drag-and-drop, they will not match
|
Mark M. |
personally, this is an area where switching to a POJO collection will probably be simpler
|
Guido |
yes makes sense
|
Mark M. |
the whole "my model is a Cursor" approach is going to fade away over time
|
Mark M. |
that was a huge win with tiny heap sizes
|
Mark M. |
it's not as much of a win now, particularly with ART's background heap compaction
|
Mark M. |
I think that's part of the reason why you're not seeing much from Google on using RecyclerView with cursors
|
Mark M. |
you certainly can -- my RecyclerView chapter demonstrates it
|
Mark M. |
but, the old rules about trying to avoid copying the Cursor data into POJOs aren't as crucial anymore
|
Mark M. |
let me take questions from the others, and I will be back with you in a bit
|
Mark M. |
Jan: your turn! do you have another question?
|
Guido |
OK, sounds good thanks
|
Jan |
Yes
|
Jan |
But not really android related : How to search your office hours archives ?
|
Mark M. |
ummm... Google?
|
Jan |
Never saw them showing up ....
|
Mar 17 | 4:35 PM |
Jan |
Are they not protected, accessible only to members
|
Mark M. |
no, they're public
|
Mark M. |
PagerAdapter site:commonsware.com
|
Guido |
Actually I'm done for tonight, many thanks for your help Mark!
|
Mark M. |
the entries whose titles are "Campfire: Today, ..." are the office hours chats
|
Mark M. |
Guido: you are very welcome!
|
Guido | has left the room |
Jan |
Ok, next time I'll try that first..... office hours archive must be a fantastic source of information :-)
|
Mark M. |
it has its advantages
|
Mark M. |
on the other hand, it's not Stack Overflow, either
|
Jan |
OK, fine
|
Jan |
That was it for me. Mark thanks a lot for your help.... until next time.
|
Mark M. |
you're welcome!
|
Jan | has left the room |
Mark M. |
Raghavendra: your turn! do you have another question?
|
Raghavendra M. |
yes
|
Raghavendra M. |
Had a question about communicating with the rest services.I am currently using volley for it.But After my client saw the code he told to use a service(I know its not a thread) that would initiate all the requests.he got inspired by a old google IO video(Google I/O 2010 - Android REST client application).He is insisting to use a service
|
Raghavendra M. |
i am not persisting any data
|
Raghavendra M. |
nor using services
|
Raghavendra M. |
no orientation change hassle
|
Mark M. |
so, right now, your REST calls are triggered just by the UI?
|
Raghavendra M. |
there is another layer which triggering
|
Raghavendra M. |
it
|
Raghavendra M. |
Ui is talking to the layer
|
Mark M. |
but the only reason a REST call is made is because the UI asks for it
|
Raghavendra M. |
mvp archi
|
Mark M. |
as opposed to being caused by other events (AlarmManager, incoming broadcasts, etc.)
|
Mar 17 | 4:40 PM |
Raghavendra M. |
is it good to just use a service
|
Raghavendra M. |
if we starting a service from activity
|
Raghavendra M. |
service will be stopped
|
Raghavendra M. |
as the activity is destroyed
|
Mark M. |
my general rule of thumb is: if the network I/O is non-essential and quick, just use a thread/AsyncTask
|
Mark M. |
if you want to feel more assured that the I/O happens, and it's of medium duration (1-10 seconds), use an IntentService
|
Raghavendra M. |
volley internally uses thread pool
|
Mark M. |
or some other flavor of service
|
Raghavendra M. |
that serves my purpose
|
Raghavendra M. |
how do i convince my client
|
Raghavendra M. |
to get away from service
|
Mark M. |
if the duration of the I/O is long (10+ seconds), use my WakefulIntentService or otherwise maintain a WakeLock
|
Mark M. |
ask the client what problem the service is solving
|
Raghavendra M. |
ohh ok
|
Raghavendra M. |
when user presses home button
|
Raghavendra M. |
or stops the activity
|
Mark M. |
the point behind a service is to raise the process priority by signalling to Android that you are doing work
|
Raghavendra M. |
he is worried aboit that
|
Mark M. |
if your app is in the foreground, you're already at high priority
|
Raghavendra M. |
ok
|
Raghavendra M. |
thats correct
|
Mark M. |
once the user moves you to the background, now issues can arise, but in your case, there will not be any new I/O once you move to the background, as I understand it
|
Mark M. |
so the only ones at any risk are I/O triggered just before the user pressed HOME or something
|
Mark M. |
and that's where the duration comes into play
|
Mark M. |
the longer the I/O time-wise, the more you need to consider a service
|
Raghavendra M. |
yes exaclty
|
Raghavendra M. |
there are some request which take time
|
Mark M. |
in which case, I would consider using an IntentService or other form of service
|
Mark M. |
those can use Volley (or any other HTTP client API) too
|
Raghavendra M. |
there are lot of request
|
Mar 17 | 4:45 PM |
Raghavendra M. |
how do i a use a single service or do i need to write multiple services
|
Mark M. |
you only need one service
|
Raghavendra M. |
ok
|
Mark M. |
call startService() for every I/O you're looking to do, with enough information for the service to know what to actually perform
|
Raghavendra M. |
in onstartcommand how will trigger different requests
|
Mark M. |
you don't want to be doing much work in onStartCommand(), as that is called on the main application thread
|
Mark M. |
beyond that, use an if or switch statement
|
Mark M. |
based on something in the Intent
|
Raghavendra M. |
there are 10 requests
|
Raghavendra M. |
10 switches is ok i guess
|
Mark M. |
well, it'd be one switch and 10 cases
|
Mark M. |
but the concept is the same
|
Raghavendra M. |
sorry for my type
|
Raghavendra M. |
u r right
|
Raghavendra M. |
startserice will be called from activity
|
Raghavendra M. |
..?
|
Raghavendra M. |
or the layer which talks to volley
|
Mark M. |
it would be called from wherever you are doing the REST calls right now
|
Raghavendra M. |
yes
|
Mark M. |
so, presumably, it would be the layer that you are referring to
|
Raghavendra M. |
wakefulintent service will be destroyed once the request completes with stopself
|
Mark M. |
IntentService/WakefulIntentService calls stopSelf() internally
|
Raghavendra M. |
yes
|
Raghavendra M. |
intent service does it
|
Raghavendra M. |
for us
|
Mark M. |
once onHandleIntent() returns, if there are no more commands to process, it will call stopSelf()
|
Mark M. |
as with your earlier questions, if you want to do more than one I/O at once, you can create your own service using a ThreadPoolExecutor
|
Raghavendra M. |
every request-->startservice
|
Mark M. |
however, then you would have to call stopSelf() yourself when the work is all done
|
Mar 17 | 4:50 PM |
Mark M. |
and yes, each operation would result in a startService() call, so the service starts up if it is not running
|
Raghavendra M. |
there will be no harm in calling that i guess
|
Raghavendra M. |
volley also spaws a thread
|
Raghavendra M. |
intent service also spawns a worked thread
|
Mark M. |
I don't use Volley, but there may be a synchronous option
|
Raghavendra M. |
but i am halfway through the project
|
Raghavendra M. |
its a major change for me
|
Mark M. |
that is between you and your client
|
Raghavendra M. |
yeah
|
Raghavendra M. |
will propose this
|
Raghavendra M. |
thanks for your time
|
Raghavendra M. |
it was really helpful
|
Mark M. |
you're welcome!
|
Mar 17 | 4:55 PM |
Raghavendra M. |
one last question u mentioned we can track progress using http client
|
Raghavendra M. |
how can we do that
|
Mark M. |
again, that would depend upon the library
|
Raghavendra M. |
server should also support right
|
Mark M. |
I have not spent much time with Volley
|
Raghavendra M. |
ok
|
Mark M. |
and so I do not know what the options are
|
Mark M. |
for an upload, the client will know how to measure progress itself
|
Raghavendra M. |
if i use other clients
|
Raghavendra M. |
how can i measure them
|
Mark M. |
for a download, if the server sends the Content-Length header, the client should be able to determine progress as well
|
Mark M. |
as I noted earlier in the chat, I have not looked at tracking progress in any client library
|
Mark M. |
sorry
|
Raghavendra M. |
sorry
|
Raghavendra M. |
for asking again
|
Raghavendra M. |
so for upload also we can get the content-length
|
Raghavendra M. |
and measure
|
Raghavendra M. |
it
|
Raghavendra M. |
thank you
|
Mark M. |
it is your file
|
Raghavendra M. |
yes
|
Mark M. |
you know how big it is
|
Raghavendra M. |
getlenth propery would give me is suppose
|
Raghavendra M. |
its just the image file coverted to base64
|
Raghavendra M. |
which is retained in memory
|
Raghavendra M. |
size is too small
|
Raghavendra M. |
in kbs
|
Mar 17 | 5:00 PM |
Raghavendra M. |
while uploading it i need to show the incremental bar
|
Raghavendra M. |
as i have told u earlier
|
Raghavendra M. |
i open to using plain http-client as well
|
Mark M. |
um, well, that's the end for today's office hours chat
|
Mark M. |
the transcript will be uploaded to http://commonsware.com/office-hours/ shortly
|
Raghavendra M. |
ok
|
Mark M. |
the next chat is Friday at 9am US Eastern
|
Mark M. |
have a pleasant day!
|
Raghavendra M. | has left the room |
Mark M. | turned off guest access |