58
ANDROID Does not Suck anymore!

Android Best Practices

Embed Size (px)

Citation preview

Page 1: Android Best Practices

ANDROID

Does not Suck anymore!

Page 2: Android Best Practices

Andy Rubin

No plans to leave Google. Oh, and just for meme completeness -- there are over 900,000 android devices activated each day :-)

Page 3: Android Best Practices

Android evolves

Page 4: Android Best Practices

http://developer.android.com/design/index.html

Android Design Patterns

Page 5: Android Best Practices

No More Menu Button

Page 6: Android Best Practices

New Buttons

Page 7: Android Best Practices

Notifications

Page 8: Android Best Practices

Navigation

Page 9: Android Best Practices

ActionBar

Page 10: Android Best Practices

Action Bar Selection

Page 11: Android Best Practices

MultiPane

Page 12: Android Best Practices

Dialogs

Page 13: Android Best Practices

Android is not ios

Page 14: Android Best Practices

IOS Design

It was cool 2 years ago

Page 15: Android Best Practices

Android is not ios

Page 16: Android Best Practices

Fragmentation

Page 17: Android Best Practices

Fragmentation

Page 18: Android Best Practices

Fragmentation

Page 19: Android Best Practices

Shut up and Show me Code Bitch!

Page 20: Android Best Practices

Android Support Jar

● V4● Fragment

● FragmentManager

● FragmentTransaction

● ListFragment

● DialogFragment

● LoaderManager

● Loader

● AsyncTaskLoader

● CursorLoader

● V13● FragmentCompat

● FragmentPagerAdapter

● FragmentStatePagerAdapter

Page 21: Android Best Practices

Support Jar

Just change the import and use latest api's

It rocks!!!

Page 22: Android Best Practices

Fragment

● Tablet and phone code comes together

● One ring to rule them all!!!

Page 23: Android Best Practices

Fragment

Define in XML

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent" android:layout_height="match_parent">

<fragment class="com.example.android.apis.app.FragmentLayout$TitlesFragment"

android:id="@+id/titles"

android:layout_width="match_parent" android:layout_height="match_parent" />

</FrameLayout>

Set Content in code

setContentView(R.layout.fragment_layout);

It works just like activity

public static class TitlesFragment extends ListFragment {

Page 24: Android Best Practices

Create Fragment

DetailsFragment f = new DetailsFragment();

// Supply index input as an argument.

Bundle args = new Bundle();

args.putInt("index", index);

f.setArguments(args);

Page 25: Android Best Practices

Fire the fragment

// Instantiate a new fragment.

Fragment newFragment = CountingFragment.newInstance(mStackLevel);

// Add the fragment to the activity, pushing this transaction

// on to the back stack.

FragmentTransaction ft = getFragmentManager().beginTransaction();

ft.replace(R.id.simple_fragment, newFragment);

ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);

ft.addToBackStack(null);

ft.commit();

Page 26: Android Best Practices

Get the parameters

@Override public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Bundle args = getArguments();

if (args != null) {

mLabel = args.getCharSequence("label", mLabel);

}

}

Page 27: Android Best Practices

Use XML

As much as you can

Page 28: Android Best Practices

Inflate Views

● Design using XML

● And @java

View v = inflater.inflate(R.layout.hello_world, container, false);

View tv = v.findViewById(R.id.text);

Page 29: Android Best Practices

DialogFragment

Better Back button support

public static class MyDialogFragment extends DialogFragment {

Page 30: Android Best Practices

Other Fragments

● ListFragment● PreferenceFragment

Page 31: Android Best Practices

Loaders

● Loader Callback MethodsonCreateLoader()

OnLoadFinished()

onLoaderReset()

Page 32: Android Best Practices

Great Man

● Jack Wharton

https://github.com/JakeWharton

Page 33: Android Best Practices

Libraries

● ActionBarSherlock● ActivityCompat2● NotificationCompat2● NineOldAndroids● SwipeToDismissNOA● Android-ViewPagerIndicator

Page 34: Android Best Practices

ActionBarSherlock

● At last you can use great ActionBar● Just use

getSupportActionBar()● Instead of

getActionBar()

Page 35: Android Best Practices

NineOldAndroids● ObjectAnimator.ofFloat(myObject, "translationY", -myObject.getHeight()).start();

AnimatorSet set = new AnimatorSet();

set.playTogether(

ObjectAnimator.ofFloat(myView, "rotationX", 0, 360),

ObjectAnimator.ofFloat(myView, "rotationY", 0, 180),

ObjectAnimator.ofFloat(myView, "rotation", 0, -90),

ObjectAnimator.ofFloat(myView, "translationX", 0, 90),

ObjectAnimator.ofFloat(myView, "translationY", 0, 90),

ObjectAnimator.ofFloat(myView, "scaleX", 1, 1.5f),

ObjectAnimator.ofFloat(myView, "scaleY", 1, 0.5f),

ObjectAnimator.ofFloat(myView, "alpha", 1, 0.25f, 1)

);

set.setDuration(5 * 1000).start();

Page 36: Android Best Practices

ViewPagerIndicator

XML<com.viewpagerindicator.TitlePageIndicator

android:id="@+id/titles"

android:layout_height="wrap_content"

android:layout_width="fill_parent" />

Page 37: Android Best Practices

ViewPagerIndicator

@Java

//Set the pager with an adapter

ViewPager pager = (ViewPager)findViewById(R.id.pager);

pager.setAdapter(new TestAdapter(getSupportFragmentManager()));

//Bind the title indicator to the adapter

TitlePageIndicator titleIndicator = (TitlePageIndicator)findViewById(R.id.titles);

titleIndicator.setViewPager(pager);

titleIndicator.setOnPageChangeListener(mPageChangeListener);

Page 38: Android Best Practices

Activity LifeCycle

Page 39: Android Best Practices

Activity LifeCycle

public class Activity extends ApplicationContext {

protected void onCreate(Bundle savedInstanceState);

protected void onStart();

protected void onRestart();

protected void onResume();

protected void onPause();

protected void onStop();

protected void onDestroy();

}

Page 40: Android Best Practices
Page 41: Android Best Practices

Send Parameter

● BundleSend

Intent data = new Intent("my.action");

data.putExtra("point", point);

data.putExtra("noqs", noqs);

Get

Bundle b = getIntent().getExtras();

noqs = b.getInt("noqs");

point = b.getInt("point");

Page 42: Android Best Practices

Send Parameter

Parcelable

protected static class Foo implements Parcelable {

public static final Parcelable.Creator<Foo> CREATOR = new Parcelable.Creator<Foo>() {

public Foo createFromParcel(Parcel source) {

final Foo f = new Foo();

f.str = (String) source.readValue(Foo.class.getClassLoader());

return f;

}

public Foo[] newArray(int size) {

throw new UnsupportedOperationException();

}

};

Page 43: Android Best Practices

Support multiple Screens

res/layout/main.xml: single-pane layout

res/layout-large: multi-pane layout

res/layout-sw600dp: multi-pane layout

res/values/layouts.xml

res/values-sw600dp-land/layouts.xml

res/values-sw600dp-port/layouts.xml

res/values-large-land/layouts.xml

res/values-large-port/layouts.xml

Page 44: Android Best Practices

Do not use px

● Use dp and sp<Button android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/clickme"

android:layout_marginTop="20dp" />

<TextView android:layout_width="match_parent"

android:layout_height="wrap_content"

android:textSize="20sp" />

Page 45: Android Best Practices

Bitmap Sizes

● xhdpi: 2.0● hdpi: 1.5● mdpi: 1.0 (baseline)● ldpi: 0.75

Page 46: Android Best Practices

Bitmap Resources

MyProject/

res/

drawable-xhdpi/

awesomeimage.png

drawable-hdpi/

awesomeimage.png

drawable-mdpi/

awesomeimage.png

drawable-ldpi/

awesomeimage.png

Page 47: Android Best Practices

UI Thread

● WTF is ANRWon't Work

handler=new Handler();

Runnable r=new Runnable()

{

public void run()

{

tv.append("Hello World");

}

};

handler.postDelayed(r, 1000);

Page 48: Android Best Practices

Android Threads

@Override

publicvoid onClick(View v){

my_button.setBackgroundResource(R.drawable.icon);

// SLEEP 2 SECONDS HERE ...

Handler handler =newHandler();

handler.postDelayed(newRunnable(){

publicvoid run(){

my_button.setBackgroundResource(R.drawable.defaultcard);

}

},2000);

}

Page 49: Android Best Practices

Android Threads

@Override

publicvoid onClick(View v){

my_button.setBackgroundResource(R.drawable.icon);

// SLEEP 2 SECONDS HERE ...

Handler handler =newHandler();

handler.postDelayed(newRunnable(){

publicvoid run(){

my_button.setBackgroundResource(R.drawable.defaultcard);

}

},2000);

}

Page 50: Android Best Practices

AsyncTask private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {

protected Long doInBackground(URL... urls) {

int count = urls.length;

long totalSize = 0;

for (int i = 0; i < count; i++) {

totalSize += Downloader.downloadFile(urls[i]);

publishProgress((int) ((i / (float) count) * 100));

// Escape early if cancel() is called

if (isCancelled()) break;

}

return totalSize;

}

protected void onProgressUpdate(Integer... progress) {

setProgressPercent(progress[0]);

}

protected void onPostExecute(Long result) {

showDialog("Downloaded " + result + " bytes");

}

}

new DownloadFilesTask().execute(url1, url2, url3);

new DownloadFilesTask().execute(url1, url2, url3);

Page 51: Android Best Practices

HTTP Libraries

You can use Apache commons

Or I found these libraries well

http://loopj.com/android-async-http/AsyncHttpClient client = new AsyncHttpClient();

client.get("http://www.google.com", new AsyncHttpResponseHandler() {

@Override

public void onSuccess(String response) {

System.out.println(response);

}

});

This works as well

http://code.google.com/p/android-query/

Page 52: Android Best Practices

Push Notifications

● Google Cloud Messaginghttp://developer.android.com/guide/google/gcm/index.html

@manifest.xml

<permission android:name="my_app_package.permission.C2D_MESSAGE" android:protectionLevel="signature" />

<uses-permission android:name="my_app_package.permission.C2D_MESSAGE" />

<receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" >

...

<intent-filter>

<action android:name="com.google.android.c2dm.intent.RECEIVE" />

<action android:name="com.google.android.c2dm.intent.REGISTRATION" />

<category android:name="my_app_package" />

</intent-filter>

</receiver>

Page 53: Android Best Practices

Push Notifications

@javaGCMRegistrar.checkDevice(this);

GCMRegistrar.checkManifest(this);

final String regId = GCMRegistrar.getRegistrationId(this);

Get regId and fire it from server

You should use this library, all other are deprecated

Page 54: Android Best Practices

Dependency Injection

● Roboguicehttp://code.google.com/p/roboguice/

● Guavahttp://code.google.com/p/guava-libraries/

Page 55: Android Best Practices

WTF is DI● Before DI

class AndroidWay extends Activity {

TextView name;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

name = (TextView) findViewById(R.id.name);

}

}

● After DI

class RoboWay extends RoboActivity {

@InjectView(R.id.name) TextView name;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

name.setText( "Hello, " + myName );

}

}

Page 56: Android Best Practices

Image Caching

● Google I/O 2012 app has a great image caching library

http://code.google.com/p/iosched/

Page 57: Android Best Practices

Open Source apps

● Google I/O 2012http://code.google.com/p/iosched/

● Github apphttps://github.com/github/android

Page 58: Android Best Practices

ListView

Most important widget

Fast ListView Tips● Inflate once

● ViewHolder

● Use Tag

● Don't write a heavy code like network operation in getView method

http://yekmer.posterous.com/fast-listview-scrolling-in-android