It has been a month since IO and in case you missed it, I got to chat with Kaushik of Fragmented. And by golly, I made it into an episode! At that point I was about to lose my voice, so I sound really husky. :p
There are some big names in the episode I am in (I still have no idea why I'm there, but I'll take it!), so please give it a listen!
PS: I travelled quite a bit after IO, but I did start a draft of my recap. I hope it sees the light of day eventually!
THIS BLOG IS DEPRECATED. I have moved to https://zdominguez.com/ Things I learned whilst writing stuff for Android, hoping to help someone save all the time I wasted trying to do things.
19 June 2016
11 June 2016
More Watches Love and a note on Context
I have previously written about debugging and how Watches can help make inspecting things in your code easier. Today, I would like to reiterate how powerful Watches can be.
When something fails in my code and I'm lucky, I would have a vague idea of what may be causing it. So I launch my app then attach the debugger (NO! to the green bug!); I am stopped at a breakpoint and while staring at the offending line, a "Wait, what if it's this other thing that's causing it?" pops into my head.
If you are used to debugging by peppering your code with Logs or Timbers or Toasts (and there's nothing wrong with that!!), you would have to stop debugging, add the logs, and re-launch your app (thank God for Instant Run!).
However, we can leverage Watches to make this process a whole lot easier. While stopped at a breakpoint, just add a new Watch (⌘+N or click the + in the Watches pane) and start typing.
Let's say for some reason I wanted to see what Intent extras, if any, had been passed into the current Activity. I just add a new Watch and put in the usual way of getting an Activity's extras -- getIntent().getExtras() and now I can inspect what I have been given when this Activity was launched. Easy peasy.
Now in the IntelliJ documentation, there is a quote that says:
Say I am now stopped at a breakpoint in a Fragment (The Frames pane says I am in the method getRandomSublist() in CheeseListFragment.java) and I would like to see the extras passed into this Fragment's host Activity. The previously added Watch will not work since in our current context -- that of a Fragment -- there is no such method getIntent(). To do what I want, I would need to call the Activity first -- getActivity().getIntent().getExtras() (= null, there are no extras received!).
Pretty coooooool. I think in a sense, you can think of Watches as coding without actually coding. Happy debugging!
When something fails in my code and I'm lucky, I would have a vague idea of what may be causing it. So I launch my app then attach the debugger (NO! to the green bug!); I am stopped at a breakpoint and while staring at the offending line, a "Wait, what if it's this other thing that's causing it?" pops into my head.
If you are used to debugging by peppering your code with Logs or Timbers or Toasts (and there's nothing wrong with that!!), you would have to stop debugging, add the logs, and re-launch your app (thank God for Instant Run!).
However, we can leverage Watches to make this process a whole lot easier. While stopped at a breakpoint, just add a new Watch (⌘+N or click the + in the Watches pane) and start typing.
Let's say for some reason I wanted to see what Intent extras, if any, had been passed into the current Activity. I just add a new Watch and put in the usual way of getting an Activity's extras -- getIntent().getExtras() and now I can inspect what I have been given when this Activity was launched. Easy peasy.
Now in the IntelliJ documentation, there is a quote that says:
Watch expressions are always evaluated in the context of a stack frame that is currently inspected in the Frames pane.Similar to the way "context" is defined in the real world (and in the Android world too, I guess) this means that Watches will only make sense if they are in used in the correct circumstance where it can be fully understood. Still confused?
Say I am now stopped at a breakpoint in a Fragment (The Frames pane says I am in the method getRandomSublist() in CheeseListFragment.java) and I would like to see the extras passed into this Fragment's host Activity. The previously added Watch will not work since in our current context -- that of a Fragment -- there is no such method getIntent(). To do what I want, I would need to call the Activity first -- getActivity().getIntent().getExtras() (= null, there are no extras received!).
Pretty coooooool. I think in a sense, you can think of Watches as coding without actually coding. Happy debugging!
25 February 2016
Taking a closer look while debugging
One of the most common sources of bugs (at least of my bugs) is math. I have been working on dynamically resizing a View the past days, and it was driving me nuts! I needed to consider preserving aspect ratio, device density, original view size, etc etc. Math is hard guys!
Thankfully, Android Studio has a bunch of tools that can help us make debugging stuff like this a little less painful.
The debug tool widnow shows you a TON of helpful information when stopped at a particular breakpoint. On the left, you can see all the calls that were done until you arrive at a particular breakpoint. Clicking on one of those will open the corresponding file and show you the exact line. A gif paints a thousand words so here you go:
The second pane shows you all variables in the currently selected file. This means that if you step through the method calls as described above, the displayed variables will change depending on that file. If you want to further inspect properties of a variable, you can expand that and do a deeper dive (this for instance, will show all inherited fields as well).
Here I can see that view is a LinearLayout, among other things. If you want to further inspect the properties of this view, you can either (1) go through the variable pane as described above, or (2) look at the params directly from that line of code.
I find Option 2 more appealing since I have more context on what I was trying to do with this variable, and if I did anything to it before or after a specific line of code. Here's option 2 in action:
Hover over the variable of interest then click on the + all the way to the left (Or ⌘+F1) then inspect to your heart's content.
You can ask Android Studio to tell you what that resolves into by asking it to evaluate the expression. Highlight interesting expression, right click, choose Evaluate Expression (alternative: highlight expression then ⌥+F8). Studio will then show you a pop up with the selected expression; you can edit the expression here as you wish. Once ready, click Evaluate and you can now see what the result would have been if this expression was actually ran.
Most of the time, however, we are not interested in computing values on the fly. We know what variable we are interested in, we know if there's any property of that variable we wanted to look at, and we know that we are doing some (possibly weird) math. This is when Watches become extremely useful. If you paid close attention to the Evaluate Expression gif, you would have noticed that there's a tiny footnote below the expression text: Use Control+Shift+Enter to add to Watches.
One way to add watches is to evaluate an expression and use the shortcut as hinted above. Another way is to highlight the expression then choose Add to Watches from the context menu. Once added you can see the expression and the evaluated value immediately in the Watches pane.
You can also manually add a Watched value by clicking on the + in the Watches pane itself. The cool thing about doing it manually? Autocomplete!!
The amazing thing and most useful thing about Watches is that the values are updated as you step through the code AND are retained across debugging sessions.
Once I step through the code (F8), the expressions in Watches are updated within the current frame's context. Notice how initially changeBounds is undefined? Step over until we hit the assignment and the value we are watching is updated.
There are a LOT more ways of maximising your mileage with Watches, so head on over to the IntelliJ blog to read all about them!
PS: Clicking on the images/gifs to embiggen should work (I hope)!
Thankfully, Android Studio has a bunch of tools that can help us make debugging stuff like this a little less painful.
The debug tool window is your friend
The debug tool widnow shows you a TON of helpful information when stopped at a particular breakpoint. On the left, you can see all the calls that were done until you arrive at a particular breakpoint. Clicking on one of those will open the corresponding file and show you the exact line. A gif paints a thousand words so here you go:
The second pane shows you all variables in the currently selected file. This means that if you step through the method calls as described above, the displayed variables will change depending on that file. If you want to further inspect properties of a variable, you can expand that and do a deeper dive (this for instance, will show all inherited fields as well).
More inspection options
One thing I love about Android Studio is that it shows you inline some pretty useful information about a variable.Here I can see that view is a LinearLayout, among other things. If you want to further inspect the properties of this view, you can either (1) go through the variable pane as described above, or (2) look at the params directly from that line of code.
I find Option 2 more appealing since I have more context on what I was trying to do with this variable, and if I did anything to it before or after a specific line of code. Here's option 2 in action:
Hover over the variable of interest then click on the + all the way to the left (Or ⌘+F1) then inspect to your heart's content.
Doing things with what we inspected
Now that we know what properties the variable we are interested in has, it's time to actually look at what we are doing with those properties. Say you are trying to arrive at a value that will depend on the height of this view. You do some basic math:view.getHeight() / 2
You can ask Android Studio to tell you what that resolves into by asking it to evaluate the expression. Highlight interesting expression, right click, choose Evaluate Expression (alternative: highlight expression then ⌥+F8). Studio will then show you a pop up with the selected expression; you can edit the expression here as you wish. Once ready, click Evaluate and you can now see what the result would have been if this expression was actually ran.
Most of the time, however, we are not interested in computing values on the fly. We know what variable we are interested in, we know if there's any property of that variable we wanted to look at, and we know that we are doing some (possibly weird) math. This is when Watches become extremely useful. If you paid close attention to the Evaluate Expression gif, you would have noticed that there's a tiny footnote below the expression text: Use Control+Shift+Enter to add to Watches.
Watches
Watches is that unassuming pane all the way to the right of the debug tool window in the very first screenshot. Here you can add any number of variables and expressions and the Watches pane will resolve them all for you in the context of the current frame (Patience grasshopper, you will soon know what this means).One way to add watches is to evaluate an expression and use the shortcut as hinted above. Another way is to highlight the expression then choose Add to Watches from the context menu. Once added you can see the expression and the evaluated value immediately in the Watches pane.
You can also manually add a Watched value by clicking on the + in the Watches pane itself. The cool thing about doing it manually? Autocomplete!!
The amazing thing and most useful thing about Watches is that the values are updated as you step through the code AND are retained across debugging sessions.
Once I step through the code (F8), the expressions in Watches are updated within the current frame's context. Notice how initially changeBounds is undefined? Step over until we hit the assignment and the value we are watching is updated.
TL;DR?
My favourite reasons for loving Watches:- I do not have to Timber or Toast or Log all the expressions I am interested in
- Evaluated expressions, but lots of them
- No need to re-add when looking at particularly nasty bugs
- Quick and easy way to view results by changing expressions on the fly
There are a LOT more ways of maximising your mileage with Watches, so head on over to the IntelliJ blog to read all about them!
PS: Clicking on the images/gifs to embiggen should work (I hope)!
22 February 2016
LinearLayouts, TextViews and Drawables
I sent out a series of tweets today about LinearLayouts and unexpectedly, quite a few people like them. I decided to get off my lazy ass and actually write it down in a post for easy reference.
Let's start with the LinearLayout root view. One of the most common things designers ask us to do is to put dividers in. Quick! Think! What should we do? Add a generic View for each divider? How about NO? Instead, we can delegate the task of displaying these dividers to the LinearLayout itself:
Where divider_horizontal_dark can be anything you want to be the divider (I recommend using a shape):
Doing this prevents us from littering our view hierarchy with useless empty views. LinearLayout is actually extremely powerful, and a lot of the stuff most apps usually need is already built in. PS: For some reason I cannot find the showDividers attribute in the Android docs, but the available attributes are middle, beginning, end, none (or a combination of those). EDIT: +Nick Butcher showed us the light: docs here!
EDIT AGAIN: Nick has also lovingly pointed out that setShowDividers() was added in API 11. If by some cruel twist of fate you need to support anything below that, use LinearLayoutCompat. Also, you poor, poor thing.
Another common thing that we are asked to do is to have an image + text displayed side by side. We use this quite a bit in the Domain app, most notably in the main navigation drawer:
Instead of having one huge RelativeLayout or (horror!) nested LinearLayouts, we can just have a bunch of TextViews in one LinearLayout.
You see, TextViews have this magical ability to add Drawables to themselves. You can position the Drawable anywhere you want, and even tint it from XML! :gasp:
Drawable placement can be in any of the cardinal directions (bottom, top, left, right) and the tint should be a defined colour in XML (not actually required, but encouraged. By me. I encourage it.). If the Drawable is too close to the text for your or your designer's taste, you can adjust the distance via the drawablePadding attribute.
So here's a screen of four TextViews in one LinearLayout:
And the full code (also in github):
If you need to update the Drawable tint at runtime (if you are basing it on some status field, for example), you can do so via code:
Note that we need to call mutate() or else the tint will be everywhere and it's gonna be a mess!
So there you have it! Remember kids, #perfmatters!
Let's start with the LinearLayout root view. One of the most common things designers ask us to do is to put dividers in. Quick! Think! What should we do? Add a generic View for each divider? How about NO? Instead, we can delegate the task of displaying these dividers to the LinearLayout itself:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
android:divider="@drawable/divider_horizontal_dark"
android:showDividers="middle">
Where divider_horizontal_dark can be anything you want to be the divider (I recommend using a shape):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#24000000" />
<size android:height="1dp" />
</shape>
Doing this prevents us from littering our view hierarchy with useless empty views. LinearLayout is actually extremely powerful, and a lot of the stuff most apps usually need is already built in. PS: For some reason I cannot find the showDividers attribute in the Android docs, but the available attributes are middle, beginning, end, none (or a combination of those). EDIT: +Nick Butcher showed us the light: docs here!
EDIT AGAIN: Nick has also lovingly pointed out that setShowDividers() was added in API 11. If by some cruel twist of fate you need to support anything below that, use LinearLayoutCompat. Also, you poor, poor thing.
Another common thing that we are asked to do is to have an image + text displayed side by side. We use this quite a bit in the Domain app, most notably in the main navigation drawer:
Instead of having one huge RelativeLayout or (horror!) nested LinearLayouts, we can just have a bunch of TextViews in one LinearLayout.
You see, TextViews have this magical ability to add Drawables to themselves. You can position the Drawable anywhere you want, and even tint it from XML! :gasp:
Drawable placement can be in any of the cardinal directions (bottom, top, left, right) and the tint should be a defined colour in XML (not actually required, but encouraged. By me. I encourage it.). If the Drawable is too close to the text for your or your designer's taste, you can adjust the distance via the drawablePadding attribute.
So here's a screen of four TextViews in one LinearLayout:
And the full code (also in github):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
android:divider="@drawable/divider_horizontal_dark"
android:showDividers="middle">
<TextView
android:id="@+id/text1"
android:drawableTop="@drawable/ic_notifications_black_24dp"
android:drawableTint="@color/lemongrab"
android:drawablePadding="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:padding="16dp"
android:text="Text 1"/>
<TextView
android:id="@+id/text2"
android:textSize="20sp"
android:drawableRight="@drawable/ic_notifications_black_24dp"
android:drawablePadding="8dp"
android:padding="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Text 2"/>
<TextView
android:id="@+id/text3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_notifications_black_24dp"
android:drawablePadding="8dp"
android:padding="16dp"
android:text="Text 3"
android:textSize="20sp"/>
<TextView
android:id="@+id/text4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_notifications_black_24dp"
android:drawablePadding="8dp"
android:padding="16dp"
android:text="Text 4"
android:textSize="20sp" />
</LinearLayout>
If you need to update the Drawable tint at runtime (if you are basing it on some status field, for example), you can do so via code:
// left, top, right, and bottom DrawableCompat.setTint(mText3.getCompoundDrawables()[0].mutate(), ContextCompat.getColor(this, R.color.red));
Note that we need to call mutate() or else the tint will be everywhere and it's gonna be a mess!
So there you have it! Remember kids, #perfmatters!
05 February 2016
Squashing Bugs
This has been one hell of a busy week for me. I think you can sort of tell from my Tweets and G+ posts that I have been debugging A LOT.
I was helping the new guy on our team look at something, and I think I almost gave him a heart attack.
App encountering what looks like random crashing? Put in some exceptionally useful Exception Breakpoints! In the Breakpoints dialog (⌘+⇧+F8 / CMD+SHIFT+F8), click on the +, choose Java Exception Breakpoints and add the exception you are interested in.
This means that even without actual breakpoints -- as long as the debugger is attached to the process -- Android Studio will suspend the process on the exact line that will throw the exception. Very easy way of narrowing down on the root cause!
But what if (God forbid!) you uncover another issue while debugging? Now you have a ton of breakpoints but you don't want to remove them because what if you still haven't fixed that other thing and this line is really important but you don't want to stop all the time. Ugh. It's a mess!
Make some semblance of order out of the chaos. Group your breakpoints. A breakpoint group can contain any number of any kind of breakpoint that Android Studio supports. This allows you to mute/unmute a set of breakpoints without having to hunt them down one by one.
Just choose the interesting breakpoints, right click, then choose Move to group. From here you can either create a new group or add them to an existing group. You can configure each breakpoint to behave how you want them to: suspend the thread, log a message, hit and forget, etc.
Here's the whole thing, in one magnificent gif.
Again, apologies to +Nick Butcher. I owe you a beer next time you're in Sydney, Nick.
I was helping the new guy on our team look at something, and I think I almost gave him a heart attack.
It takes FOREVER to launch the app when you click that green bug. I hate that green bug. Save yourself some heartache:Scared new guy when I yelled "NOOO!" as he was about to click green bug. Run then attach when debugging. #AndroidDev pic.twitter.com/cFUNKDu0f1— Zarah Dominguez (@zarahjutz) February 5, 2016
- Put in your breakpoints
- Launch the app as you normally would
- Navigate to the offending activity
- Attach Debugger to Android Process
App encountering what looks like random crashing? Put in some exceptionally useful Exception Breakpoints! In the Breakpoints dialog (⌘+⇧+F8 / CMD+SHIFT+F8), click on the +, choose Java Exception Breakpoints and add the exception you are interested in.
This means that even without actual breakpoints -- as long as the debugger is attached to the process -- Android Studio will suspend the process on the exact line that will throw the exception. Very easy way of narrowing down on the root cause!
But what if (God forbid!) you uncover another issue while debugging? Now you have a ton of breakpoints but you don't want to remove them because what if you still haven't fixed that other thing and this line is really important but you don't want to stop all the time. Ugh. It's a mess!
Make some semblance of order out of the chaos. Group your breakpoints. A breakpoint group can contain any number of any kind of breakpoint that Android Studio supports. This allows you to mute/unmute a set of breakpoints without having to hunt them down one by one.
Just choose the interesting breakpoints, right click, then choose Move to group. From here you can either create a new group or add them to an existing group. You can configure each breakpoint to behave how you want them to: suspend the thread, log a message, hit and forget, etc.
Here's the whole thing, in one magnificent gif.
Again, apologies to +Nick Butcher. I owe you a beer next time you're in Sydney, Nick.
02 November 2015
Annotating all (or most of) the things
If, like me, you are old and have been developing for Android for a while, you should, like me, appreciate the fact that the backwards compatibility of the OS has come a long way. Sure, they may toy with my feelings from time to time, but we all need a little excitement every now and then.
I have recently decided that I will invest more time into learning how all the tools at an Android developer's disposal can make me code better, faster, cleaner, and less buggy (I initially said "buggier" because I want to rhyme but someone who supposedly does English better complained).
To start with, I have been trying recently to consistently use the Resource Type annotations. These annotations prevent code like this from exploding:
This will explode because:
1. Fields are named horrendously
2. Without reading what the method does, it is so easy to pass the wrong resource ID (I can only assume that it wants resource IDs)
Resource annotations help with reason #2 by letting you and the compiler know just what type of resource is expected. There are a lot of available annotations (Read the docs!) but I find that the things I use the most are, well, the things I use the most:
@StringRes - expects an R.string.*
@DrawableRes - expects an R.drawable.*
@IdRes - expects an R.id.*
@ColorRes - expects an R.color.*
I have updated my SDK Sandbox project with an Activity to illustrate use of these annotations. FAIR WARNING: IT USES ENUMS. If this annoys you, DO NOT click through.
So how do we stop the method above from exploding? Let's fix all the things!
Ahhh. Easy. And so much better.
I have recently decided that I will invest more time into learning how all the tools at an Android developer's disposal can make me code better, faster, cleaner, and less buggy (I initially said "buggier" because I want to rhyme but someone who supposedly does English better complained).
To start with, I have been trying recently to consistently use the Resource Type annotations. These annotations prevent code like this from exploding:
private void setThingsToTextView(int res1, int res2, int res3, int res4) {
// do stuff
}
This will explode because:
1. Fields are named horrendously
2. Without reading what the method does, it is so easy to pass the wrong resource ID (I can only assume that it wants resource IDs)
Resource annotations help with reason #2 by letting you and the compiler know just what type of resource is expected. There are a lot of available annotations (Read the docs!) but I find that the things I use the most are, well, the things I use the most:
@StringRes - expects an R.string.*
@DrawableRes - expects an R.drawable.*
@IdRes - expects an R.id.*
@ColorRes - expects an R.color.*
I have updated my SDK Sandbox project with an Activity to illustrate use of these annotations. FAIR WARNING: IT USES ENUMS. If this annoys you, DO NOT click through.
So how do we stop the method above from exploding? Let's fix all the things!
private void setThingsToTextView(@IdRes int textView, @StringRes int introText, @DrawableRes int heroImage, @ColorRes int backgroundColour) {
// do stuff
}
Ahhh. Easy. And so much better.
23 September 2015
NOT another day at the office
We had another round of Innovation Day at Domain last month, and I wrote about it. We started out dreaming up this ambitious project -- too ambitious for two days! Here's a partial list of what we had to do:
- Build a wall
- Stick devices on said wall
- Make app that cycles through photos from listings
- Load said app on those devices that we stuck to the wall
- Figure out how to track people who get devices
- What if someone just gets a device?!
- Figure out how to let people give back devices
- Oh! oh! oh! Wouldn't it be cool if other devices cheer when one of them "comes home"?
- How do we put new versions of the app on those devices?
- Run tests, maybe?
- What if the website team wants to test responsive designs?
- Do they even charge????!!!
It was a LOT of work. But it was awesome.
15 September 2015
In Which Things Got Cheesy
Today, Android Developers published Domain's Developer Story. In it, Gary and Rique talked about how the Domain Android app was rated very poorly and had all sorts of problems. Fast forward two years and it is now a highly-rated, top-ranked lifestyle app in Australia. You would think that going from a 2.8 star rating to 4.1 stars is all sorts of amazing. And it is!
Rique mentioned how 2014 was a really big year for Domain; in a very personal sense, it was for me too. This video coming out gave me pause and kicked off a bit of a melancholy spell for me.
Around the middle of last year, I packed up half of my clothes, left all of my books and games, said goodbye to my family and my friends and my love, and moved to Australia. The choice to relocate was hard, and I almost didn't take it. I was just about to accept a new job at a big OEM, my boyfriend and I just bought an apartment, my friends and I have regular game nights -- everything was going really well. I really had no plans of going anywhere, I have long given up on the overseas dream. And then BAM, the Universe decides to spring this surprise onto me; and out of nowhere came this chance to work on something I truly enjoy doing.
I am so lucky and grateful to have been a part Domain's journey over the past year. The app did a lot of growing up, so did I.
Rique mentioned how 2014 was a really big year for Domain; in a very personal sense, it was for me too. This video coming out gave me pause and kicked off a bit of a melancholy spell for me.
Around the middle of last year, I packed up half of my clothes, left all of my books and games, said goodbye to my family and my friends and my love, and moved to Australia. The choice to relocate was hard, and I almost didn't take it. I was just about to accept a new job at a big OEM, my boyfriend and I just bought an apartment, my friends and I have regular game nights -- everything was going really well. I really had no plans of going anywhere, I have long given up on the overseas dream. And then BAM, the Universe decides to spring this surprise onto me; and out of nowhere came this chance to work on something I truly enjoy doing.
I am so lucky and grateful to have been a part Domain's journey over the past year. The app did a lot of growing up, so did I.
My tech life has grown by leaps and bounds since I've moved to Sydney. Yay? Yay!
— Zarah Dominguez (@zarahjutz) June 30, 2015
I have possibly learned SO MUCH over the past year than the three years before that combined. Sure, it can get lonely being alone in a foreign country. Of course I miss my mom. Of course I miss my boyfriend. I surely do miss my friends -- I can never get anyone to play board games with me here. But at the same time, I have been meeting a lot of really great, really awesome people. I have learned how to cook (it turns out I can make a great cranberry feta salad, which technically is not cooking, but whatever). I have been on a lot of adventures, traveled to cool new places, jumped out of a plane, drank a lot of beer.
Who has the best team ever? I do! Got to the office with this on my desk. :) pic.twitter.com/a0knGn9kXD
— Zarah Dominguez (@zarahjutz) August 23, 2015
Plus, I DO have the best team ever. :)
10 September 2015
Raising Activities From the Dead
One of the scenarios I admittedly almost always forget to test is "What happens when my app goes into the background, then the OS kills is to claim memory, then I try to resume?" Usually it's "Well, I handle onSavedInstanceState not being null, so I am great!" It is fine and dandy for simple apps; but once your Activity or Fragment gets beefier and you start relying on state for more and more things, it can get complicated pretty quickly (In my case, the Fragment has setRetainInstance(true)).
This scenario in particular is kind of hard to reproduce willingly. I usually see this when I leave an app running, make my phone do some heavy work overnight, then resume the app the next day.
3. Push your app to the background. Pressing the HOME button should be sufficient. This will call onSaveInstanceState, which is all that matters really. It is after all what we want to test.
4. Back in Studio, press the magical tiny red button pointed to in the previous image. Notice that Studio now appends [DEAD] to your app's process. It is now gone. He's dead, Jim!
5. Resume your app. I usually just do this via recent apps.
6. If you look at Studio, you'll see that your app is now no longer dead, but has a new process ID, in this case 26742.
This scenario in particular is kind of hard to reproduce willingly. I usually see this when I leave an app running, make my phone do some heavy work overnight, then resume the app the next day.
So what you gonna do?
It turns out that Android Studio has the answer! There is this magical tiny red button that allows you to simulate this exact scenario.
1. Open your app to the Activity you want to test (I use a very simple app here just for demo).
2. In Studio, go to Android Monitor (make sure that your app is selected). Note the process ID, in this case it is 25647.
3. Push your app to the background. Pressing the HOME button should be sufficient. This will call onSaveInstanceState, which is all that matters really. It is after all what we want to test.
4. Back in Studio, press the magical tiny red button pointed to in the previous image. Notice that Studio now appends [DEAD] to your app's process. It is now gone. He's dead, Jim!
5. Resume your app. I usually just do this via recent apps.
6. If you look at Studio, you'll see that your app is now no longer dead, but has a new process ID, in this case 26742.
If at this point you step through your code, you will notice that your Activity will go through the whole (re-)creation process with the Bundle given the values you have saved in onSaveInstanceState. No more waiting overnight, yay!
12 August 2015
Lies I've been told today
So I played around with data binding today. And these are the lies that the dev guide told me (explicitly or inferred):
- There is a method DataBindingUtil.bindTo(viewRoot, layoutId)
- That this will work MyLayoutBinding.bind(viewRoot);
- Android Studio has auto-complete
Subscribe to:
Posts (Atom)

















