I do not read..I’ll just ask someone what’s new on Android Android Pitfalls and Anti-patterns Jigar Brahmbhatt I do not read..I’ll just ask someone what’s new on Android I read your blog…it’s fantastic…can you share your source code so I can copy paste ? I don’t know enough Java, but I would love to do Android development Is this already available in Support Library ? Since When? Just making this Context static to get work done! Will remove it later What is AsyncLayoutInflater ? velopment move it later Oh yeah! I know what is abstraction in OOPS! Got full marks in college exam What do you mean by “context is leaking” ? Oh it’s an easy fix! Let me just put a NULL check before it Hey dude, don’t worry about Android lint! bunch of warnings huah! Dead code ! Dead code! Dead code! How to freaking know when my user is online and offline ? PM requirement! android:screenOrientation=“portrait" Yay! doSomething(null, null, true, null, false) Javadoc ? Who’s gonna read? public static String MY_GLOBAL_STRING = “”; ne ? PM requirement! I don’t know enough Java, but I would love to do Android development Is this already available in Support Library ? Since When? Just making this Context static to get work done! Will remove it later Oh yeah! I know what is abstraction in OOPS! Got full marks in college exam What do you mean by “context is leaking” ? Oh it’s an easy fix! Let me just put a NULL check before it Dead code ! Dead code! Dead code! Javadoc ? Who’s gonna read? public static String MY_GLOBAL_STRING = “”; ine ? PM requirement! BOOT_COMPLETED Code reviews ? YAGNI “Don’t Repeat Yourself” What is AsyncLayoutInflater ? d development @jabbar_jigariyo
Objective Conferences are not about teaching specifics, but all about inspiring and enlightening At work, one may find a guide or mentor, but at the end everything depends on self-learning 2
# 1 Language Problem 8 ‣ Android is a framework, not language ‣ Excitement for Android without understanding Java (recent grads) ‣ Knowledge of OOPS, but don’t utilize ‣ Poor or lack of understanding related to design patterns
editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { // process the text, and do something }
@Override public void afterTextChanged(Editable s) {
} }); public abstract class MyBaseTextWatcher implements TextWatcher { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // Do nothing }
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { // Do nothing }
@Override public void afterTextChanged(Editable s) { // Do nothing } } Example: Utilizing OOPS concepts
public abstract class MyBaseTextWatcher implements TextWatcher { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // Do nothing }
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { // Do nothing }
@Override public void afterTextChanged(Editable s) { // Do nothing } } editText.addTextChangedListener(new MyBaseTextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // process the text, and do something } });
public abstract class MyBaseTextWatcher implements TextWatcher { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // Do nothing }
@Override public void onTextChanged(CharSequence s, int start, int before, int count) { // Do nothing }
@Override public void afterTextChanged(Editable s) { // Do nothing } } editText.addTextChangedListener(new MyBaseTextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // process the text, and do something } });
Example: Solving a problem with better design pattern public enum PaymentType { PAYTM, FREECHARGE }
public void pay(PaymentType paymentType, String phone) { if(paymentType == PaymentType.PAYTM) { // process with paytm using phone } else { // process with freecharge using phone } }
Example: Solving a problem with better design pattern public enum PaymentType { PAYTM, FREECHARGE }
public void pay(PaymentType paymentType, String phone) { if(paymentType == PaymentType.PAYTM) { // process with paytm using phone } else { // process with freecharge using phone } }
// if freecharge, email is required public void pay(PaymentType paymentType, String phone, String email) throws IllegalStateException { if(paymentType == PaymentType.PAYTM) { // process with paytm using phone } else if(!TextUtils.isEmpty(email)){ // process with freecharge using phone and email } else { // error state because payment type is // freecharge but email is null or empty throw new IllegalStateException("blah blah"); } }
// if freecharge, email is required public void pay(PaymentType paymentType, String phone, String email) throws IllegalStateException { if(paymentType == PaymentType.PAYTM) { // process with paytm using phone } else if(!TextUtils.isEmpty(email)){ // process with freecharge using phone and email } else { // error state because payment type is // freecharge but email is null or empty throw new IllegalStateException("blah blah"); } }
public enum PaymentType { PAYTM, FREECHARGE, BLAH, BLAH2..... }
public void pay(PaymentType paymentType, String phone, String email, .......) throws IllegalStateException { switch (paymentType) { case PAYTM: // check for phone number break; case FREECHARGE: // check for phone and email, or fail break; .......... .......... } }
public enum PaymentType { PAYTM, FREECHARGE, BLAH, BLAH2..... }
public void pay(PaymentType paymentType, String phone, String email, .......) throws IllegalStateException { switch (paymentType) { case PAYTM: // check for phone number break; case FREECHARGE: // check for phone and email, or fail break; .......... .......... } }
28 ‣ FragmentTransaction.commitAllowingStateLoss(); This is dangerous because the commit can be lost if the activity needs to later be restored from its state, so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.
‣ Old APIs == no bug fixes, no new features ‣ Can’t provide useful input if you’re not up-to-date IF YOU’RE NOT READING..WE’RE NOT HIRING YOU!!!!!! @Haptik
‣ Old APIs == no bug fixes, no new features ‣ Can’t provide useful input if not up-to-date ‣ Writing unnecessary code because you don’t know what is already available IF YOU’RE NOT READING..WE’RE NOT HIRING YOU!!!!!! @Haptik
‣ Old APIs == no bug fixes, no new features ‣ Can’t provide useful input if not up-to-date ‣ Writing unnecessary code because you don’t know what is already available if(phone != null && !phone.isEmpty()) { // Do something } IF YOU’RE NOT READING..WE’RE NOT HIRING YOU!!!!!! @Haptik
‣ Old APIs == no bug fixes, no new features ‣ Can’t provide useful input if not up-to-date ‣ Writing unnecessary code because you don’t know what is already available if(phone != null && !phone.isEmpty()) {}
// instead of “android.text.TextUtils" if(!TextUtils.isEmpty(phone)) { // phone is ready to use } IF YOU’RE NOT READING..WE’RE NOT HIRING YOU!!!!!! @Haptik
// Commented out below method! It’s not working out // // public void thisMethodIsNotWorking(String phone) { // this.phone = phone; // // if(phone != null && !phone.isEmpty()) { // Something is not working // } // // // instead of // if(!TextUtils.isEmpty(phone)) { // probably this is not right // } // } ‣ If you’re sole developer or early stage startup then, you are suffering from spaghetti code everywhere
‣ Too many 3rd party libs! Choose wisely Update cycle Deprecation issue Bugs Too much utility for your own usage Size impact (Realm) You MUST understand how it works
# 6 Let me check for NULL problem! QA/Lead: Hey, there is a crash with “Null Pointer Exception” in Crashlytics! You: Aah, should be an easy fix! Give me a sec!
QA/Lead: Hey, there is a crash with “Null Pointer Exception” in Crashlytics! You: Aah, should be an easy fix! Give me a sec! if(view != null) { view.doSomething(); }
‣ Avoid allowing NULL in your method arguments ‣ Use method overloading make more appropriate methods ‣ Provide factory methods ‣ Use power of annotations! @Nullable @NonNull
@Override public void onSuccess() { if (progressDialog != null) { progressDialog.dismiss(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); progressDialog = new ProgressDialog(this); } Fatal Exception: java.lang.IllegalArgumentException: View=com.android.internal.policy.PhoneWindow$DecorView{9c3d915 V.E...... R......D 0,0-1026,348} not attached to window manager at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.jav a:424) at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java: 350) at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.ja va:116) at android.app.Dialog.dismissDialog(Dialog.java:362) at android.app.Dialog.dismiss(Dialog.java:345)
# 7 Lint - Ignorance is not bliss! ‣ Lint is your best friend! (Part QA too) ‣ Tackle literally every lint warning! If you find a false positive, then suppress it!
# 9 APK or AAR size ignorance! ‣ Drawables (most unoptimized and ignored area, but highest impact on size) ‣ Not utilizing proguard ‣ Model classes vs direct JSON
Ending note! ‣ Aim to understand the code you’re adding! ‣ Make sure that it is easy to understand and readable ‣ Take some time, and learn something new every week
You MUST aim to read 100% of these websites! https://codelabs.developers.google.com https://github.com/googlesamples https://developer.android.com/guide/index.html https://www.youtube.com/user/androiddevelopers/