the rounds project: growing from thousands to millions - berry ventura & yoahy barsky, rounds
TRANSCRIPT
•Fun, eyecandy, social, viral, useful
Thank you Product Team!
•Scalable, fast, reliable, predictable backend
Thank you Server Team!
•Great Client side
That’s us! The Rounds Android Team
Yohay, Berry, Shay, Vadim and growing...
The Key for a Great App
•Supporting as many devices,
OS versions and languages as possible
•Robust, Crash-free app
•Responsive UI, using latest guidelines
•Surprise & Delight the user
Great Client Side
Android 4.03 and above
Only about 8% of users use
Froyo, Gingerbread & below
so...
we only support 4.03 and above
(release quicker, use newer features).
Support 7130 devices
QA?
Code Reviews
In house test most popular devices
Applause for testing all over the world
TestFairy for usability videos
Support 7130 devices
Release:
Start with 20% rollout
Crashlytics for amazing crash analytics
Increase after a few days
Responsive UI ?
•Used new Thread() every time
Oh no! Don’t do that!!
•Used synchronized on UI thread
Argh! Blocked it and got nasty ANRs!
•Fetched again the same info from server
Users had to wait…
Use a ThreadPool!
•Changed every call of
new Thread(someRunable).start();
•To
RoundsExecutor.get().execute(someRunable);
•And the result
With a few hours work
Amazing improvement in performance!
public class RoundsExecutor {
private static ExecutorService sPool =
Executors.newCachedThreadPool();
public static ExecutorService get() {
return sPool;
}
private RoundsExecutor(){ }
}
•synchronized, do you really need it?
avoid it completely on UI thread
if yes…
code review anyway
•pay attention where you are running.
if it is a callback then…
who is calling?
Parallel Threads Beware
IntentService
•Creates a single background thread
•Will process only one task at a time
•Send the service an intent with what to do
Use LocalBroadcastManager
to broadcast event with result
Use a BroadcastReceiver
to handle result on UI thread
Managing Data
Model Persist Locally
Notify when changed
Servers
UI
Widgets
Activity or
Fragment
Fetch from Server
Managing Data
Model Persist Locally
Notify when changed
Servers
UI
Widgets
Activity or
Fragment
Fetch from Server Persist in Server
Managing Data
Model Persist Locally
Notify when changed
Servers
UI
Widgets
Activity or
Fragment
Fetch from Server GCM / XMPP Push Persist in Server
Managing Data
Model Persist Locally
Notify when changed
Servers
UI
Widgets
Activity or
Fragment
Fetch from Server GCM / XMPP Push Persist in Server
Persisting Data
We use
SharedPreferences for simple data
SQLLite for more complicated data
UniversalImageLoader for images
We wanted an IntentService that would
•reschedule tasks that failed
•schedule tasks for later
•stay alive until we asked it to stop
github.com/rounds/rounds-android-goodies
FlexibleIntentService
•Any component can broadcast events
using LocalBroadcastManager
•Any component can declare events
it is interested in and how to handle them
public interface RoundsBroadcastListener {
public String [] getInterests();
public void handleRoundsEvent(String
action, Bundle extras);
}
Event Pipeline
We developed our handler
mHandler =
new RoundsEventHandler(context,
roundsBroadcastListener)
Base classes that implement the listener
And use our handler
RoundsActivityBase
RoundsFragmentBase
Event Pipeline
Start listening at onResume()
mHandler.registerReceivers();
Stop listening at onPause()
mHandler.unregisterReceivers();
github.com/rounds/rounds-android-goodies
Event Pipeline
yeti_eyes.xml
<animation-list android:oneshot="false" >
<item
android:drawable="@drawable/yeti_eyes_1"
android:duration="3000"/>
<item
android:drawable="@drawable/yeti_eyes_2"
android:duration="50"/>
…etc ….
</animation-list>
How to make a Yeti Blink
How to make a Yeti Blink
•Create an animation-list xml resource
that lists frame by frame images
•To mimic a live object use
Random duration values
•On the ImageView you want to animate:
yetiEyes.setBackgroundResource(
R.drawable.yeti_eyes)
How to make a Yeti Blink
Animate yetiEyes ImageView with
AnimationDrawable yetiEyesAnimation =
(AnimationDrawable) yetiEyes.getBackground();
yetiEyesAnimation.start();
Summary
•Make great product that people want to use
•Keep basic design principles in mind
•Use tools & services for crash free app
•Add Fun Surprises & Delights
•Can’t get it perfect the first time
•Keep learning and improve as you go
Thank You! [email protected] | [email protected]