Office Hours — Today, September 15

Wednesday, September 9

Sep 15
8:55 AM
Mark M.
has entered the room
Mark M.
turned on guest access
MyWay
has entered the room
MyWay
hi Mark
Mark M.
hello, MyWay!
how can I help you today?
MyWay
I'm using ViewPager with ArrayPagerAdapter, anything is working fine, but I have added a badge from which users can jump to a specific Fragment selecting the User in the drawer. Now, if the Fragment exists there is no problem and I'm returning its position from a loop mAdapter.getExistingFragment(i)) checking it's title/tag (I know it in advance), else I don't know where to jump. So, the user has a list in the right drawer and he knows in advance that there are new messages from a specific User, but when he taps on one of these user in the list, I don't know always the position. How can I force the ViewPager to create the needed fragment in that istant so that I can get the position and jump to the right position? Currently I'm receveing inside the Activity, from my Service (using EventBus) a call and I'm doing this: http://pastebin.com/xwbvrsf9 but mQueryFragment is != null only if the ViewPager instantiate it.
Bryan
has entered the room
Mark M.
(BTW, hello, Bryan -- I will be with you shortly!)
Bryan
Hi, np
Mark M.
MyWay: well, the ViewPager doesn't create fragments
the adapter creates fragments
and the adapter only does so on demand
9:00 AM
MyWay
but it is the viewpager asking to do, right?
when the user swipe
Mark M.
yes, but only if there is a position for it
IOW, if your page count is 7, and you ask for position 3439, you'll crash somewhere
or at best be ignored
MyWay
what I'm trying to do is forcing it to add a new position so that I can jump the user to it
can I do it?
Mark M.
you are certainly welcome to add a new entry to the ArrayPagerAdapter
that's part of the reason I wrote it :-)
but ViewPager itself won't ever trigger that
MyWay
infact I'm adding it from the code: mAdapter.add(new SimplePageDescriptor(sQuery.toLowerCase(), sQuery));
Mark M.
OK
MyWay
but I still have the problem that I don't have a position returned
Mark M.
add() appends to the e4nd
er, end
so, the position is your page count minus one
(page count as calculated post-add)
(which also means your new position is your page count as calculated before the add() call)
let me take a question from Bryan while you mull that over, and I'll be back with you in a bit
MyWay
but why if I'm doing a loop for (int i = 0; i < mAdapter.getCount(); i++) { after adding it
Mark M.
Bryan: your turn! do you have a question?
MyWay
I don't have this fragment here?
oh sorry
Bryan
I have a notification who's pending intent on click goes to my MainActivity (only activity for my app), there is a function that handles that intent and then shows the correct fragment based on the type of notification. The "shows the correct fragment part" clears out the fragmentmanager backstack and then starts a new stack by inserting the starting fragment, then immediately showing the fragment they want.
right before this I clear out the backstack (if there was one), so it all starts fresh.
9:05 AM
Bryan
The problem is that sometimes, when clearing the backstack, I get a IllegalStateException: Can not perform this action after onSaveInstanceState
not everytime, just sometimes
I am not as saavy as I would like on lifecycle stuff, so I was wondering if you had any ideas to point me in the right direction
Mark M.
um, well, let's back up a bit
Bryan
:), sure
Mark M.
by default, your PendingIntent would be creating a new instance of the activity
presumably, you're doing something to change that behavior
Bryan
let me check
Mark M.
are you using Intent flags? launchMode in the manifest?
Bryan
notificationBuilder.setContentIntent(PendingIntent.getActivity(this, 0, contentIntent, PendingIntent.FLAG_ONE_SHOT));
Mark M.
are you adding any flags to contentIntent?
Bryan
checking
View paste
Intent contentIntent = new Intent(this, MainActivity.class);
contentIntent.setAction(Intent.ACTION_VIEW);
contentIntent.putExtra(EXTRA_NOTIFICATION_GROUP, pn.getNotification_group());
then just setting data
Mark M.
OK, do you have android:launchMode set in the manifest for this activity?
Bryan
SingleTask
Mark M.
ah, there we go
Bryan
*singleTask
Mark M.
do you really want to be reusing the activity in this case? or would you prefer to just wipe out the old activity (if it exists) and start a new one fresh?
9:10 AM
Bryan
I would have to think through if there were any issues, but let's say that I am open to whichever works best
I know that we had other issues when I had the launchmode to singleActivity
unfortunately, I don't remember what they were
Mark M.
my gut instinct would be to start fresh, rather than trying to rework the existing activity instance
Bryan
ok
what would I change to move towards that?
also, could you explain what the issue is
as you see it
Mark M.
to do that, call addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) on the contentIntent before wrapping it in the PendingIntent
Bryan
re: "ah, there we go"
ok
Mark M.
though I have never tried this in concert with singleTask launchMode, so YMMV
the "ah, there we go" was trying to understand why you had a back stack in the first place :-)
in terms of what the problem is...
while I have seen that error before, usually to me it means "you have wandered too far off the path of the Way of Fragments"
Bryan
lol, that would be a fair guess
Mark M.
which is why, all else being equal, I'd rather wipe out the old activity and start anew, rather than trying to retrofit the existing activity instance
Bryan
ok, thanks! I will try the flag above and see how that goes!
Mark M.
that being said, without code, I have no way of telling you why you might get that error, and I probably can't even *with* code, in the confines of a chat
Bryan
that makes sense
Mark M.
it's the sort of thing that given a mostly-working app and a way to reproduce the problem, I can probably find the culprit
Bryan
yeah, we haven't found the way to reproduce at this point
Mark M.
but I don't have a roster of likely culprits to offer
Bryan
just got this yesterday though, so still working through it
Mark M.
let me switch back to MyWay, and I'll swing back to you in a bit
MyWay: your turn!
Bryan
sounds good
MyWay
I meant, I'm adding the Fragment to the adapter, then I'm looping over getCount (http://pastebin.com/FYhHjZBw (getting -1)), now from what I've understand I should find the Fragment I'm searching for (which should be the last), but it's not here, maybe that it has not been added yet?
9:15 AM
Mark M.
no, add() does not create the fragment
add() adds the descriptor
and makes it possible to create the fragment when the ViewPager asks for the fragment
MyWay
so how can I jump to this fragment? I add it to the adapter, but then I need viewpager to ask for it
Mark M.
"so how can I jump to this fragment?" -- call setCurrentPosition() on the ViewPager with the position
whoops, sorry, setCurrentItem()
where the position is adapter.getCount()-1
after calling add()
MyWay
ok, then I've added many descriptors by calling add()
but still not swiped or moved the viewpager
how do I find the position? :P
should I store it when I'm adding?
Mark M.
as I wrote, "where the position is adapter.getCount()-1"
where "adapter" is your ArrayPagerAdapter
MyWay
yes, but it's getCount()-1 when you add only one
if I add 10 and want the 5?
Mark M.
why are you adding 10 pages, based on a single click by the user?
MyWay
is there a way to loop over them and search by knowing in advance the title/tag, or I should store?
it's a single click, they are irc events
Mark M.
so?
9:20 AM
MyWay
if the user receives 10 messages from 10 differents users, the drawer has 10 items in the listview
then the user tap on one of them, but I've already added them to the adapter
(them all)
Mark M.
then you already know the position
after all, you added the page
and at that time, you knew the position
MyWay
so I should store it
Mark M.
well, yes
MyWay
ok, thank you
Mark M.
let me take another question from Bryan, and I'll be back with you shortly
Bryan: your turn! do you have another question>
er, ?
Bryan
Yes, ok, so the issue that got me to even try the clearing the back stack was this
I have a current backstack: Page 1 > Page 2 > Page 3
i get a notification with a pending intent that my activity launches a "Page 2" fragment
so then I am Page 1 > Page 2 > Page 3 > Page 2
so when I hit back twice I get "fragment already added" exception
make sense?
aka "am I thinking of that right" ?
Mark M.
wait, both "Page 2" entries in your back stack are the same fragment instance?
Bryan
I think so
Mark M.
that's unlikely to work well
Bryan
I think that is why I am getting the error, I assumed that it would handle it automatically
but that isn't the case
Mark M.
having two fragment instances both backed by the same "Page 2" data would be fine
9:25 AM
Bryan
does givng it a different tag to the fragmentmanager
ensure a distince instance?
*distinct
Mark M.
no
Bryan
how do I ensure that?
Mark M.
*you* are the one creating instances, when putting them in the FragmentManager
so, you create new instances by calling the constructor on the fragment, or the factory method, or whatever
Bryan
yeah, i wrote some functions that do that automatically, so it is the past me that is at fault here
the current me can't be held responsible
Mark M.
fire up the DeLorean and slap your past you with a trout :-)
Bryan
:), Ok, I will look to see if I can make sure I do a separate instance for the second part
if I can't find that
Mark M.
(and, if convenient, slap the past me a few times with that trout, as I'm sure I deserve it for something)
Bryan
ha
Mark M.
are these pages read only? or are they forms to be filled in
?
Bryan
read only
Mark M.
ah, cool
then two fragment instances should be OK
Bryan
they have buttons and whatnot, but they are just for viewing
I was trying to resuse to save memroy
Mark M.
which is fine, but I don't think the back stack is sophisticated enough for that
Bryan
yeah, I am finding that out. The problem is that even though I use "replace" the backstack code deep in the bowels does a remove and add
so it throws that error
seems "wrong" somehow, but who am I to say that
thanks again
Mark M.
well, fragments are kinda bolted onto the side of Android
they're odd in general
(and don't get me started on nested fragments...)
Bryan
:)
9:30 AM
Mark M.
I've long since given up on "right" and "wrong" and settled for "seems stable" and "breaks even despite the pentagram of dried bat blood I sprinkled on the floor"
Bryan
good to know! I just felt like I was the only kid in class that didn't "get it"
Mark M.
let's just say that while I'm not in Square's "fragments are the work of the devil" camp, I feel their pain
let me take another question from MyWay, and I'll swing back to you shortly
MyWay: your turn! do you have another question?
MyWay
Currently when the app is in background, my Service is caching all IRC Events. As memory is not infinite, can I use onLowMemory() call to remove some event? Or it's a bad practice?
Mark M.
what's your minSdkVersion?
MyWay
the one of Android 4, can't remember the number
Mark M.
OK, that'd be at least 14
in which case, a typical caching approach is to use an LRU or similar approach to prevent you from blowing out your heap, then use onTrimMemory() to try to progressively "tighten your belt" while you are in the background
MyWay
yes
Mark M.
onLowMemory() was primarily for pre-API Level 14 devices; onTrimMemory() covers everything onLowMemory() does, with more granularity
MyWay
this seems reasonable
9:35 AM
Mark M.
many developers skip the onTrimMemory() approach, most likely
that's a "be a good citizen" thing to do
MyWay
why?
Mark M.
as onTrimMemory() helps the *user* but doesn't really impact your app much
other than perhaps keeping your process alive a bit longer
MyWay
ah, so they don't care
Mark M.
I'd phrase it more as "it's way down on the to-do list"
for those that know it's something that can be done, at any rate
MyWay
:P
Mark M.
I don't even emphasize it much in my book, though I probably should
MyWay
ok, thank you
Mark M.
those sorts of things that have no direct benefit on the developer (or the developer's boss) tend not to get a lot of attention
until such time as Google drops the hammer, as in Android 6.0
and its "war on background processing"
MyWay
yes, I'm just doing this app for fun
and to learn
Mark M.
and because you still use IRC :-)
MyWay
ahah, yes
Mark M.
*vaguely remembers IRC*
MyWay
eheh
Mark M.
ooo... I hadn't realized that Campfire recognized IRC slash commands like /me
MyWay
:P
Mark M.
anyway, let me switch back to Bryan for a bit
Bryan: your turn! do you have another question?
9:40 AM
Mark M.
OK, if either of you have a question, go right ahead
MyWay
I have an inner class, OutputArrayAdapter extending ArrayAdapter inside a Fragment, can this cause memory leaks? I always read that inner class is bad, because it keeps outer reference, but what happens with adapters' class inside fragments?
Mark M.
well, that depends on the scope of your OutputArrayAdapter instance
I assume this is an adapter for a ListView or something shown by the Fragment?
MyWay
yes
Mark M.
then unless you are doing something strange, you should be OK
the problem with inner classes come when you use the inner class for something with scope outside its outer class
for example, if you have an inner class implementation of SensorEventListener, when you register it with SensorManager, you will leak the outer class instance until you unregister it
MyWay
but if I have a method which is returning the adapter, is it a problem?
Mark M.
if that method is being called by something beyond the life of the fragment, potentially, yes
MyWay
so I should avoid doing it
Mark M.
having the method? yes
MyWay
yes
Mark M.
keep it within the fragment
have the fragment expose an API for doing what needs doing
that is better encapsulation anyway, in case you switch implementations (e.g., move to RecyclerView)
MyWay
ok
9:45 AM
MyWay
if Bryan is not here, I have a last question
Bryan
I am here
I have one more short question
Mark M.
Bryan: go right ahead!
Bryan
Is there a good resource out there to reference (more from a tutorial standpoint) for messing with the innards of fragments/backstack, etc?
Mark M.
the source code
beyond that, I can't really name anything
Bryan
ok, cool, thanks Mark!
have a good one
Mark M.
if either of you have a question, chime in
MyWay
Always about Leaks, I've tried playing with the device monitor and MAT, e.g. I got this http://i58.tinypic.com/2yzbdwp.png and after 15 minutes (disconnection/connection/configurationChange), I got this: http://i59.tinypic.com/ff90mw.png now... I can not see differences, it seems difficult to analyze to find leak, do you have any suggestion?
Mark M.
well, it may not be a "leak"
as you noted, you are caching stuff like IRC messages
cache growth = heap growth
MyWay
yes
9:50 AM
Mark M.
in MAT, I usually focus on finding instances of my classes that should not be cached, plus looking for big things that should not be cached
MyWay
but from logcat (Mint) I'm getting OutOfMemoryException on: rootView = inflater.inflate(R.layout.userlist, container, false); unfortunately the log is incomplete and I have no idea what is causing it (only a device seems to have this problem)
the list does not contain images, nothing
just a list of string (user nicknames)
Mark M.
bear in mind that OOM does not mean that you are out of heap space, but that there is no single free block big enough for your request
the Dalvik GC engine is non-compacting
(and ART only compacts when your app is in the background)
so your heap can be fragmented
MyWay
ah
Mark M.
usually, an OOM on an inflate() call is triggered by android:background
as Android did not have a big enough block of memory for your drawable resource that you are using for the background
MyWay
my background is ?android:attr/windowBackground
Mark M.
any reason why you need that, versus it just having no background at all?
MyWay
not that I can remember of
Mark M.
try removing android:background, see if your UI still looks OK, and if it does, see if it helps with the OOM when you release an update
9:55 AM
MyWay
yes, thank you
Mark M.
it's possible there's something else in the layout that would trigger an OOM on inflation, but backgrounds tend to be the biggest culprit, based on what I've seen through Stack Overflow questions
MyWay
I finished the questions, thank you very much, as always
Mark M.
happy to be useful!
MyWay
maybe fastscroll?
Mark M.
pardon?
MyWay
I haven't set anything
android:fastScrollEnabled="true"
Mark M.
possibly, but I haven't heard of that being an issue
MyWay
ok, I will try with the background, thanks again
10:00 AM
Bryan
has left the room
MyWay
Have a nice day, bye
MyWay
has left the room
Mark M.
turned off guest access

Wednesday, September 9

 

Office Hours

People in this transcript

  • Bryan
  • Mark Murphy
  • MyWay