Office Hours — Today, December 18

Thursday, December 13

Dec 18
9:50 AM
Mark M.
has entered the room
9:55 AM
Mark M.
turned on guest access
Marcin
has entered the room
Mark M.
howdy, Marcin
how can I help you today?
Marcin
Hi Mark
I have an activity and fragment
activity has a loader and loader callback
i would like fragment to have a loader as well and implement callback
problem is fragment doesnt have getSupportLoaderMagaaer
10:00 AM
Mark M.
call getLoaderManager()
that returns the right LoaderManager class based on the Fragment class
so, the Android Support backport Fragment returns an Android Support backport LoaderManager
Marcin
oh.. thanks
in case i would have one loadermanager and many loaders
how do i handle :
public void onLoadFinished(Loader<Boolean> arg0, Boolean arg1) {
?
Mark M.
I am sorry, but I do not understand your question
Marcin
when I initialize Loader, I pass ID (int)
Mark M.
correct
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//
now=know
10:05 AM
Mark M.
you pass in *different* instances of LoaderCallbacks<> for each Loader that uses the same data type
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
well, let me rephrase that
you could do some sort of if/else-if/else stuff, checking to see which Loader object it is
personally, I would use distinct callbacks
Marcin
makes sense
10:10 AM
Marcin
View paste
Is this a proper way to check if configuration change occured?
public void onCreate(Bundle savedInstanceState ) {
            super .onCreate(savedInstanceState ); 
            if( savedInstanceState != null ){
Mark M.
that is a typical approach
Marcin
ok
regarding this question
Mark M.
are you referring to your comment on the answer?
Marcin
yes
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.
(now posted as a comment from me on the answer)\
Marcin
thanks
i have an app which i will redesign/reimplement
10:15 AM
Marcin
im looking for a best pattern to do this
this is the app
Mark M.
um, your question is too broad for this chat
Marcin
basically its a listing of deals/merchants
to simplyfy it, two tabs in actionbar
two lists
and nothing else
this is what i came up with for this fundament
asynctaskloader will update db
while taking data from zend server
the cursorloader will update the listview through contentobserver
LM = loadermanager
Mark M.
OK... so what is your specific question?
10:20 AM
Marcin
lets say i have contentprovider and listview with curosrloader
i run asynctaskloader every 200m
it updates db
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)
?
Mark M.
that I cannot answer
that is dependent upon the implementation of CursorLoader and your ContentProvider
10:25 AM
Marcin
possible though?
Mark M.
that is dependent upon the implementation of CursorLoader
it is the one registering the ContentObserver
it will only find out about events pertaining to that registratino
er, registration
Marcin
it is used like that
View paste
return new CursorLoader(this.getActivity(),
				ccContentProvider.CONTENT_URI_MERCHANTS, new String[] {}, null,
				null, null);
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
10:30 AM
Marcin
im thinking in contentproviders query (get 100 merchants)
do something like c.setNotificationUri
passing Uri pattern for single merchant row
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."
10:35 AM
Mark M.
the ContentObserver system works on Uri values, not patterns
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.
inside activity onCreate method i do
View paste (3 more lines)
ActionBar actionBar = getSupportActionBar();
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
		actionBar.setDisplayShowTitleEnabled(false);
		Tab tab = actionBar
				.newTab()
				.setText(R.string.tab_merchants)
				.setTabListener(
						new TabListener<MerchantsListFragment>(this,
								"merchant", MerchantsListFragment.class));
		actionBar.addTab(tab);

		tab = actionBar
				.newTab()
				.setText(R.string.tab_deals)
				.setTabListener(
...
all works well
10:40 AM
Marcin
but.. when i rotate once
i can see : MerchantsListFragment - onDestroy, MerchantsListFragment - onCreate
which is ok
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)
Marcin: you see what "msg" twice?
Marcin
MerchantsListFragment - onDestroy, MerchantsListFragment - onCreate
this is log from relevant methods
so when i rotate twice
MerchantsListFragment - onDestroy, MerchantsListFragment - onCreate
MerchantsListFragment - onDestroy, MerchantsListFragment - onCreate
and so on
Mark M.
then somewhere you are creating multiple instances of that fragment
if I had to guess, your problem lies in your implementation of TabListener<MerchantsListFragment>
let me take a question from Andrew, and I can swing back to you in a bit if there is still time
Andrew: do you have a question?
Marcin
spot on
thanks
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
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
what is "this behavior" that I am supposed to have "observed"?
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
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
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
you are welcome to attempt to use android:launchMode instead
that is simply not a pattern I use, and therefore am not expert in all of its ramifications
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"
(with "not appropriate for most applications" in red)
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
it was my understanding that should resume a TASK in its curent state
not relaucnh L
Mark M.
that varies by app
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
I've not seen this flag before FLAG_ACTIVITY_REORDER_TO_FRONT
you would use this in the onResume() of L?
Mark M.
the default behavior is to return to N
for example, I just tested EmPub, the app that drives the APK edition of my book
opened the book, tapped on the action bar item to go into settings, pressed HOME
tapped the icon in the launcher, and I was returned to the settings activity (N)
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
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)
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
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
have a pleasant day, all!
Marcin
has left the room
Andrew G.
has left the room
Mark M.
turned off guest access

Thursday, December 13

 

Office Hours

People in this transcript

  • Andrew Gibel
  • Marcin
  • Mark Murphy

Files in this transcript