Dec 18 | 9:50 AM |
Mark M. | has entered the room |
Dec 18 | 9:55 AM |
Mark M. | turned on guest access |
Marcin | has entered the room |
Mark M. |
howdy, Marcin
|
Mark M. |
how can I help you today?
|
Marcin |
Hi Mark
|
Marcin |
I have an activity and fragment
|
Marcin |
activity has a loader and loader callback
|
Marcin |
i would like fragment to have a loader as well and implement callback
|
Marcin |
problem is fragment doesnt have getSupportLoaderMagaaer
|
Dec 18 | 10:00 AM |
Mark M. |
call getLoaderManager()
|
Mark M. |
that returns the right LoaderManager class based on the Fragment class
|
Mark M. |
so, the Android Support backport Fragment returns an Android Support backport LoaderManager
|
Marcin |
oh.. thanks
|
Marcin |
in case i would have one loadermanager and many loaders
|
Marcin |
how do i handle :
|
Marcin |
public void onLoadFinished(Loader<Boolean> arg0, Boolean arg1) {
|
Marcin |
?
|
Mark M. |
I am sorry, but I do not understand your question
|
Marcin |
when I initialize Loader, I pass ID (int)
|
Mark M. |
correct
|
Mark M. |
you also pass an instance of LoaderCallbacks for your desired data type (e.g., Cursor)
|
Marcin |
how I will now without an ID which loader is it inside (onLoadFinished) - assuming that I need something like instanceof//
|
Marcin |
now=know
|
Dec 18 | 10:05 AM |
Mark M. |
you pass in *different* instances of LoaderCallbacks<> for each Loader that uses the same data type
|
Mark M. |
for example, your activity could implement
LoaderCallbacks<> for its Loader, and your fragment could
implement LoaderCallbacks<> for its Loader
|
Marcin |
ok. thought i could do a switch like during initialization and id
|
Mark M. |
I do not see how
|
Mark M. |
well, let me rephrase that
|
Mark M. |
you could do some sort of if/else-if/else stuff, checking to see which Loader object it is
|
Mark M. |
personally, I would use distinct callbacks
|
Marcin |
makes sense
|
Dec 18 | 10:10 AM |
Marcin |
View paste
|
Mark M. |
that is a typical approach
|
Marcin |
ok
|
Marcin | |
Marcin |
regarding this question
|
Mark M. |
are you referring to your comment on the answer?
|
Marcin |
yes
|
Marcin |
sorry, forgot to mention
|
Mark M. |
"would CursorLoader be restarted even if I update
db through SQLiteDatabase instead of ContentProvider?" -- no. You have
to do all updates through the ContentProvider, and the ContentProvider
has to make the appropriate calls to tie into the observer framework.
|
Mark M. |
(now posted as a comment from me on the answer)\
|
Marcin |
thanks
|
Marcin |
i have an app which i will redesign/reimplement
|
Dec 18 | 10:15 AM |
Marcin |
im looking for a best pattern to do this
|
Marcin |
this is the app
|
Marcin | |
Mark M. |
um, your question is too broad for this chat
|
Marcin |
basically its a listing of deals/merchants
|
Marcin |
to simplyfy it, two tabs in actionbar
|
Marcin |
two lists
|
Marcin |
and nothing else
|
Marcin | |
Marcin |
this is what i came up with for this fundament
|
Marcin |
asynctaskloader will update db
|
Marcin |
while taking data from zend server
|
Marcin |
the cursorloader will update the listview through contentobserver
|
Marcin |
LM = loadermanager
|
Mark M. |
OK... so what is your specific question?
|
Dec 18 | 10:20 AM |
Marcin |
lets say i have contentprovider and listview with curosrloader
|
Marcin |
i run asynctaskloader every 200m
|
Marcin |
it updates db
|
Marcin |
will this automatically update the listview in this design?
|
Mark M. |
only if the AsyncTaskLoader is using a ContentResolver to update the ContentProvider
|
Marcin |
if it updates through contentresolver with uri1
(for specific merchants) .. will that refresh the listview if it is tied
with Uri2 - (get 100 merchants)
|
Marcin |
?
|
Mark M. |
that I cannot answer
|
Mark M. |
that is dependent upon the implementation of CursorLoader and your ContentProvider
|
Dec 18 | 10:25 AM |
Marcin |
possible though?
|
Mark M. |
that is dependent upon the implementation of CursorLoader
|
Mark M. |
it is the one registering the ContentObserver
|
Mark M. |
it will only find out about events pertaining to that registratino
|
Mark M. |
er, registration
|
Marcin |
it is used like that
|
Marcin |
View paste
|
Mark M. |
you will need to read through the source to
CursorLoader to see if it will behave how you want with the updates you
are trying to do
|
Marcin |
guess it automatically registers this Uri
|
Mark M. |
probably
|
Marcin |
ok, will do
|
Mark M. |
which means updates that the ContentProvider say pertain to that Uri will trigger an update to that CursorLoader
|
Dec 18 | 10:30 AM |
Marcin |
im thinking in contentproviders query (get 100 merchants)
|
Marcin |
do something like c.setNotificationUri
|
Marcin |
passing Uri pattern for single merchant row
|
Marcin |
from setNotificationUri docs : "Register to watch a
content URI for changes. This can be the URI of a specific data row
(for example, "content://my_provider_type/23"), or a a generic URI for a
content type."
|
Dec 18 | 10:35 AM |
Mark M. |
the ContentObserver system works on Uri values, not patterns
|
Mark M. |
though I am not completely clear on what "a generic URI for a content type" would mean here
|
Marcin |
i will play with it..
|
Mark M. |
it definitely works on collections
(content://my_provider_type or content://authority/type) and instances
(content://my_provider_type/5 or content://authority/type/17)
|
Marcin |
.. I have an activity with 2 tabs inside action bar.
|
Marcin |
inside activity onCreate method i do
|
Marcin |
View paste
(3 more lines)
|
Marcin |
all works well
|
Dec 18 | 10:40 AM |
Marcin |
but.. when i rotate once
|
Marcin |
i can see : MerchantsListFragment - onDestroy, MerchantsListFragment - onCreate
|
Marcin |
which is ok
|
Marcin |
then i turn again and i see that msg twice
|
Andrew G. | has entered the room |
Marcin |
then i rotate i see it three times
|
Andrew G. |
ugh I keep forgetting these are EST
|
Mark M. |
(howdy, Andrew -- be with you shortly)
|
Mark M. |
Marcin: you see what "msg" twice?
|
Marcin |
MerchantsListFragment - onDestroy, MerchantsListFragment - onCreate
|
Marcin |
this is log from relevant methods
|
Marcin |
so when i rotate twice
|
Marcin |
MerchantsListFragment - onDestroy, MerchantsListFragment - onCreate
|
Marcin |
MerchantsListFragment - onDestroy, MerchantsListFragment - onCreate
|
Marcin |
and so on
|
Mark M. |
then somewhere you are creating multiple instances of that fragment
|
Mark M. |
if I had to guess, your problem lies in your implementation of TabListener<MerchantsListFragment>
|
Mark M. |
let me take a question from Andrew, and I can swing back to you in a bit if there is still time
|
Mark M. |
Andrew: do you have a question?
|
Marcin |
spot on
|
Marcin |
thanks
|
Dec 18 | 10:45 AM |
Mark M. |
Andrew: do you have a question?
|
Andrew G. |
My question is about manifest
<launchmode="xx"> it seems to behave differently than the docs
would leave me to belive and is perhaps even device specific. I have an
'emial-like' program with a main inbox, a compose message screen, a
view contacts screen, etc. I have the inbox set to singleTop and the
others set to singleInstance since I want the user to only have one
instance of those Activities on the stack at any given time. What I"m
seeing when the user leaves the app (on some devices) they are returned
to the singleTop Inbox instead of the singleInstnace Activity that they
left from. Before I had this complicated state machine in the Intray to
relaunch the closed Activity but that really shouldn't be needed
|
Mark M. |
personally, I avoid android:launchMode to the greatest extent possible
|
Andrew G. |
then how can you ahcieve what I mentioned above?
|
Mark M. |
in particular singleInstance
|
Andrew G. |
but with standard it seems to always return you to your launcher Activity
|
Andrew G. |
Are you saying it is correct to relaunch manually based on saved state?
|
Mark M. |
I am saying that I personally avoid android:launchMode to the greatest extent possible
|
Andrew G. |
have you not observed this behavior then?
|
Mark M. |
you are asking me, in a matter of seconds, to
digest your paragraph, comprehend what you are trying to achieve, and
come up with an alternative
|
Mark M. |
what is "this behavior" that I am supposed to have "observed"?
|
Mark M. |
if you are referring to "with standard it seems to
always return you to your launcher Activity", depending on the value of
"it", the behavior will vary based upon whether your process is already
running and other criteria
|
Dec 18 | 10:50 AM |
Mark M. |
for example, if "it" is "tapped on the home
screen's launcher icon", it will bring an existing task to the
foreground if your process is already running, or start a new process
(in a new task, typically) if your process is not already running
|
Mark M. |
rolling all the way back to your paragraph, I tend
to control activity instances via FLAG_ACTIVITY_REORDER_TO_FRONT and
kin as flags on the Intent
|
Mark M. |
you are welcome to attempt to use android:launchMode instead
|
Mark M. |
that is simply not a pattern I use, and therefore am not expert in all of its ramifications
|
Mark M. |
note that the documentation states "The other
modes — singleTask and singleInstance — are not appropriate for most
applications, since they result in an interaction model that is likely
to be unfamiliar to users and is very different from most other
applications"
|
Mark M. |
(with "not appropriate for most applications" in red)
|
Mark M. | |
Andrew G. |
When you have multiple Activities - only one of
them configured as a "launcher" call this L. A user is on a
non-launcher Activity (Activity N) that was launched from L then hits
HOME. It is my observation that the user is always returned to L on
resume. I can't believe that Android is always killing that process so
quickly each time that it is restarting it
|
Mark M. |
define "on resume"
|
Andrew G. |
when the user clicks the launcher for the app again
|
Andrew G. |
it was my understanding that should resume a TASK in its curent state
|
Andrew G. |
not relaucnh L
|
Mark M. |
that varies by app
|
Dec 18 | 10:55 AM |
Mark M. |
for example, Gmail on my Galaxy Nexus returns me to N, while Contacts returns me to L
|
Andrew G. |
Right. But prefering the first behavior over the second of those you've just mentioned - it must be configurable
|
Andrew G. |
I've not seen this flag before FLAG_ACTIVITY_REORDER_TO_FRONT
|
Andrew G. |
you would use this in the onResume() of L?
|
Mark M. |
the default behavior is to return to N
|
Mark M. |
for example, I just tested EmPub, the app that drives the APK edition of my book
|
Mark M. |
opened the book, tapped on the action bar item to go into settings, pressed HOME
|
Mark M. |
tapped the icon in the launcher, and I was returned to the settings activity (N)
|
Mark M. |
and I have not set android:launchMode in any of those activities to the best of my recollection
|
Andrew G. |
This behavior seems to differ by device. That is why I'm trying to explicityly control it
|
Mark M. |
if the behaviors differs by device, and it is not a
case of some devices being short on RAM and terminating the process
rapidly, that's a bug in the device, IMHO
|
Mark M. |
and, off the cuff, I have no idea how I'd go about forcing this behavior for recalcitrant devices
|
Andrew G. |
Well it looks like launchMode does what it wants anyway :) Guess I'm back to relaunching Activities based on saved global state
|
Mark M. |
with respect to FLAG_ACTIVITY_REORDER_TO_FRONT,
you put that as a flag in an Intent for use with startActivity(), to
bring an existing instance to the foreground (if it exists) or create it
(if it does not)
|
Dec 18 | 11:00 AM |
Andrew G. |
ah. That's helpful actually. At least I don't have to worry about multiple stack instances
|
Mark M. |
and that's a wrap for today's chat
|
Mark M. |
next one is Thursday at 4pm Eastern
|
Marcin |
thanks Mark, have a nice evng
|
Andrew G. |
Sorry to seem like I was rushing you - promise to actually get here on time for that one!
|
Mark M. |
the transcript will be posted at http://commonsware.com/office-hours/ shortly
|
Mark M. |
have a pleasant day, all!
|
Marcin | has left the room |
Andrew G. | has left the room |
Mark M. | turned off guest access |