- MergeSort
- Time Complexity: Worse case - O(nLogn)
- Auxiliary Space: O(n)
- Application: Used in External Sorting
Friday, February 19, 2016
Sorting & Searching - Update in progress
Fragment Android - Update In Progress
- Fragment is a small chunk of UI, process its own events and has its own lifecycle
- can be added/ removed in to activity
- Introduced in Honeycomb, but can be used from 1.6 using support library.
Need of Fragments
- Can combine several fragments in single Activity
- Fragments can be re-used across several activity
- Make use of larger screen
- Fragment Lifecycle
- Fragment & Activity combined Lifecycle
- Adding Fragment in to Activity
- XML
- runtime
- Inter Fragment communication pattern
- Managing fragment in backstack
- Fragments in ViewPager
- FragmentPagerAdapter
- FragmentStatePagerAdapter
- can be added/ removed in to activity
- Introduced in Honeycomb, but can be used from 1.6 using support library.
Need of Fragments
- Can combine several fragments in single Activity
- Fragments can be re-used across several activity
- Make use of larger screen
- Fragment Lifecycle
- Fragment & Activity combined Lifecycle
- Adding Fragment in to Activity
- XML
- runtime
- Inter Fragment communication pattern
- Managing fragment in backstack
- Fragments in ViewPager
- FragmentPagerAdapter
- FragmentStatePagerAdapter
Android Studio Tips
- Module build command
- gradlew build -p moduleA ( moduleA is the module subDirectory name )
Key Shortcuts
CTL + N - go to class
CTL + SHIFT + N - go to file
CTL + ALT+ SHIFT + N - go to symbol
ALT + Right/Left - go to next/previous editor
CTL + F12 - list class variables
SHIFT + F6 - rename
CTL + Y - delte line
CTL + ALT + M - extract method;
ALT + Delete - safe delete
ADB Commands
adb shell dumpsys meminfo package_name
adb shell ps | findstr -i search_string
adb shell pm list packages -f | findstr -i search_string
adb shell kill -3 PID
adb shell getprop | findstr -i prod
adb shell getprop | findstr -i ex
adb logcat -v time | findstr -i packagetest
apktool.bat d apk_path target_dir
dex2jar.bat apk_path
adb shell ps | findstr -i search_string
adb shell pm list packages -f | findstr -i search_string
adb shell kill -3 PID
adb shell getprop | findstr -i prod
adb shell getprop | findstr -i ex
adb logcat -v time | findstr -i packagetest
apktool.bat d apk_path target_dir
dex2jar.bat apk_path
Tuesday, February 9, 2016
Intent & Intent-Filters
Intent
Note: Beginning with Android 5.0 (API level 21), the system throws an exception if you call bindService() with an implicit intent.
Building an Intent
Using a Pending Intent
Intent Resolution
- TBU
- Messaging Object
- Can be used to request an action from another component.
- Facilitate communication between components in several ways.
- Start an activity.
- Start a service.
- Deliver a broadcast.
- Explicit intents: Specify the name by component class name. Can be used only to start a component in your own app.
- Implicit intents: Specify the general action to be performed, which allows component from other app to handle it.
Note: Beginning with Android 5.0 (API level 21), the system throws an exception if you call bindService() with an implicit intent.
Building an Intent
- Intent object carries information that the Android system uses to determine which component to start.
- Component Name: Name of the component, Optional for implicit intent but critical for explicit intent.
- Action Name : Specifies the generic action to perform.
- Data: The URI (a Uri object) that references the data to be acted on and/or the MIME type of that data
- Category: Additional information about the kind of component that should handle the intent
- Extras: Key-value pairs that carry additional information required to accomplish the requested action.
- Flag: flags instruct the Android system how to launch an activity.
- Declare intent filters for each of your app components with an <intent-filter> element in your manifest file.
- Each intent filter specifies the intent's action, data, and category.
- The system will deliver an implicit intent to your app component only if the intent can pass through one of your intent filters.
Using a Pending Intent
- PendingIntent object is a wrapper around an Intent object.
- Grants permission to other application use the contained Intent as it is executed from your own app process.
Intent Resolution
- TBU
Painless threading in Android UI
Main or UI thread:
- in charge of dispatching the events to the appropriate widgets & drawing event.
- ANR happens if UI thread blocked for more than 5 secs.
- the Android UI toolkit is not thread-safe and must always be manipulated on the UI thread.
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable, long)
- Handler
Android Runtime (ART) Feature
Ahead-of-time compilation
ELF - Executable and Linkable Format.
Improved garbage collection
- At install time, ART compiles apps using the on-device dex2oat tool.
ELF - Executable and Linkable Format.
Improved garbage collection
- One GC pause instead of two
Google Cloud Messaging
Google Cloud Messaging for Android (GCM) is a service that allows you to send data from your server to your users' Android-powered device, and also to receive messages from devices on the same connection.
Steps to follow to receive GCM notification in Android Client App
1. Write Broadcast Receiver class which extends WakefulBroadcastReceiver and handle the intent action in onReceive method
Please refer below example
Declare the components in AndroidManifest.xml
GcmPushNotificationReceiver.java
GcmIntentService.java
Steps to follow to receive GCM notification in Android Client App
1. Write Broadcast Receiver class which extends WakefulBroadcastReceiver and handle the intent action in onReceive method
Please refer below example
Declare the components in AndroidManifest.xml
<!-- GCM Push Notification --> <!-- Broadcast Receiver to receive the GCM notification from GCM Agent --> <receiver android:name=".notification.GcmPushNotificationReceiver" android:permission="com.google.android.c2dm.permission.SEND" > <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> </intent-filter> </receiver> <!-- Service to handle in intent action --> <service android:name="notification.GcmIntentService" > </service> <!-- GCM Push Notification -->
GcmPushNotificationReceiver.java
import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.support.v4.content.WakefulBroadcastReceiver; import android.util.Log; public class GcmPushNotificationReceiver extends WakefulBroadcastReceiver { private static final String TAG = GcmIntentService.class.getSimpleName(); @Override public void onReceive(Context context, Intent intent) { if(Debug.DEBUG_LOW) Log.i(TAG, "onReceive action = "+intent.getAction()); // Explicitly specify that GcmMessageHandler will handle the intent. ComponentName comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName()); // Start the service, keeping the device awake while it is launching. startWakefulService(context, (intent.setComponent(comp))); setResultCode(Activity.RESULT_OK); } }
GcmIntentService.java
import com.google.android.gms.gcm.GoogleCloudMessaging; import android.app.IntentService; import android.content.Intent; import android.os.Bundle; import android.util.Log; public class GcmIntentService extends IntentService { private static final String TAG = GcmIntentService.class.getSimpleName(); public GcmIntentService(String name) { super(name); } @Override protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this); // The getMessageType() intent parameter must be the intent you received // in your BroadcastReceiver. String messageType = gcm.getMessageType(intent); if(Debug.DEBUG_LOW) Log.i(TAG, "GcmIntentService Received : (" +messageType+") "+extras.getString("title")); GcmPushNotificationReceiver.completeWakefulIntent(intent); } }
Customize volley default retry Policy & Cache timeout
Volley Default request retry policy:
/** The default socket timeout in milliseconds */
public static final int DEFAULT_TIMEOUT_MS = 2500;
/** The default number of retries */
public static final int DEFAULT_MAX_RETRIES = 1;
/** The default backoff multiplier */
public static final float DEFAULT_BACKOFF_MULT = 1f;
Volley does retry for you if you have specified the policy.
Client app can change retry values for each request using below API.
setRetryPolicy(new DefaultRetryPolicy (TIMEOUT_MS, MAX_RETRIES, BACKOFF_MULT ));
Example Timeout - 3000 secs, Num of retry - 2, Back Off Multiplier - 2
Attempt 1:
- time = time + (time * Back Off Multiplier );
- time = 3000 + 6000 = 9000
- Socket Timeout = time;
- Request dispatched with Socket Timeout of 9 Secs
Attempt 2:
- time = time + (time * Back Off Multiplier );
- time = 9000 + 18000 = 27000
- Socket Timeout = time;
- Request dispatched with Socket Timeout of 27 Secs
Steps to change Volley default Cache Hit & Cache time-out values:
1. Create new Volley Request class.
2. Set custom cacheHit & cacheTimeout values in parseNetworkResponse callback method.
Please refer below example.
GsonRequest.Java
HttpHeaderParser.java - only new method added
/** The default socket timeout in milliseconds */
public static final int DEFAULT_TIMEOUT_MS = 2500;
/** The default number of retries */
public static final int DEFAULT_MAX_RETRIES = 1;
/** The default backoff multiplier */
public static final float DEFAULT_BACKOFF_MULT = 1f;
Volley does retry for you if you have specified the policy.
Client app can change retry values for each request using below API.
setRetryPolicy(new DefaultRetryPolicy (TIMEOUT_MS, MAX_RETRIES, BACKOFF_MULT ));
Example Timeout - 3000 secs, Num of retry - 2, Back Off Multiplier - 2
Attempt 1:
- time = time + (time * Back Off Multiplier );
- time = 3000 + 6000 = 9000
- Socket Timeout = time;
- Request dispatched with Socket Timeout of 9 Secs
Attempt 2:
- time = time + (time * Back Off Multiplier );
- time = 9000 + 18000 = 27000
- Socket Timeout = time;
- Request dispatched with Socket Timeout of 27 Secs
Steps to change Volley default Cache Hit & Cache time-out values:
1. Create new Volley Request class.
2. Set custom cacheHit & cacheTimeout values in parseNetworkResponse callback method.
Please refer below example.
GsonRequest.Java
import java.io.UnsupportedEncodingException; import java.util.Map; import android.util.Log; import com.android.volley.AuthFailureError; import com.android.volley.DefaultRetryPolicy; import com.android.volley.NetworkResponse; import com.android.volley.ParseError; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.Response.ErrorListener; import com.android.volley.Response.Listener; import com.android.volley.toolbox.HttpHeaderParser; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonSyntaxException; import com.samsung.android.guardian.utils.Config; public class GsonRequest<T> extends Request<T> { private static final String TAG = GsonRequest.class.getSimpleName(); private final Gson gson; private final Class<T> clazz; private final Map<String, String> headers; private final Listener<T> listener; private int cacheHit; private int cacheExpiry; public GsonRequest(int method, String url, Class<T> clazz, Map<String, String> headers, Listener<T> listener, ErrorListener errorListener) { super(method, url, errorListener); //Using default volley retry policy //If retry policy has to be changed use setRetryPolicy methods from each request objects if(Config.VOOLEY_USE_DEFAULT_RETRY_POLICY){ setRetryPolicy(new DefaultRetryPolicy( DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); } GsonBuilder gsonBuilder = new GsonBuilder(); this.gson = gsonBuilder.create(); this.clazz = clazz; this.headers = headers; this.listener = listener; this.cacheHit = Config.DEFAULT_CACHE_HIT; this.cacheExpiry = Config.DEFAULT_CACHE_EXPIRY; } /** * @param method - GET/POST/PUT/DELETE * @param url - server URL * @param clazz - class represents server response * @param headers * @param listener - listener for success case * @param errorListener - listener for failure case * @param cacheHit - time milliseconds, after this time cache will be hit, but also refreshed on background. * 0 for CacheHit = CacheExpiry case * @param cacheExpiry - time milliseconds, after this time cache entry expires completely */ public GsonRequest(int method, String url, Class<T> clazz, Map<String, String> headers, Listener<T> listener, ErrorListener errorListener, int cacheHit, int cacheExpiry) { this(method,url, clazz, headers, listener, errorListener); this.cacheHit = cacheHit; this.cacheExpiry = cacheExpiry; } @Override public Map<String, String> getHeaders() throws AuthFailureError { return headers != null ? headers : super.getHeaders(); } @Override protected void deliverResponse(T response) { listener.onResponse(response); } @Override protected Response<T> parseNetworkResponse(NetworkResponse response) { try { String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); Log.i(TAG,"parseNetworkResponse data "+json); if(Config.VOOLEY_USE_DEFAULT_CACHE_TIMEOUT){ //Volley default Cache return Response.success(gson.fromJson(json, clazz), HttpHeaderParser.parseCacheHeaders(response)); }else{ // Apply custom cache return Response.success(gson.fromJson(json, clazz), HttpHeaderParser.parseIgnoreCacheHeaders(response, cacheHit, cacheExpiry)); } } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JsonSyntaxException e) { return Response.error(new ParseError(e)); } } }
HttpHeaderParser.java - only new method added
public static Cache.Entry parseIgnoreCacheHeaders(NetworkResponse response, int cacheHit, int cacheExpiry) { long now = System.currentTimeMillis(); Map<String, String> headers = response.headers; long serverDate = 0; String serverEtag = null; String headerValue; headerValue = headers.get("Date"); if (headerValue != null) { serverDate = parseDateAsEpoch(headerValue); } serverEtag = headers.get("ETag"); final long ttl = now + cacheExpiry; final long softExpire; if(cacheHit > 0){ softExpire = now + cacheHit; }else{ softExpire = ttl; } Log.i(TAG, "parseIgnoreCacheHeaders softExpire: "+softExpire+", ttl:"+ttl); Cache.Entry entry = new Cache.Entry(); entry.data = response.data; entry.etag = serverEtag; entry.softTtl = softExpire; entry.ttl = ttl; entry.serverDate = serverDate; entry.responseHeaders = headers; return entry; }
AsyncTask
- Allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
- Should ideally be used for short operations. (use java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask for long running thread).
- Define 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.
- Async Task uses ThreadPoolExecutor to run multiple tasks at same time. total thread size = CPU Count * 2 + 1.
- AsyncTask must be subclassed to be used.
- The task instance must be created on the UI thread.
- AsyncTask callback methods are thread safe.
AsyncTask<Params, Progress, Result>
params....
execute(params....) (ex: execute(url1, url2, url3))
- params are passed to doInBackground method which is being executed in worker thread
publishProgress(Progress...)
- being called inside doInBackground, Progress... value passed to method onProgressUpdate running in UI Thread.
- return result.... return value from doInBackground passed to onPostExecute
isCancelled()
- returns true is task been cancelled using API cancel(boolean)
- Before DONUT - no thread pool in AsyncTask
- After DONUT - Thread Pool introduced and by default task are executed in multiple thread.
- After HONECOMP - by default tasks are being executed in single thread to avoid error. use executeOnExecutor(Executor exec, Params... params) API to enable true parallel execution.
- AsyncTask has two static Executor instance SERIAL_EXECUTOR & THREAD_POOL_EXECUTOR
Java concurrency
- The use of synchronized methods or statements provides lock acquisition and release to occur in a block-structured way.
- Lock interface enables lock to be acquired and released in different scopes, and allowing multiple locks to be acquired and released in any order.
The Lock interface provides more extensive locking operations than it's possible to obtain via synchronized methods and statements
methods:
- void lock()
- void lockInterruptibly()
- Condition newCondition()
- boolean tryLock()
- boolean tryLock(long time, TimeUnit unit)
- void unlock()
- ReentrantLock(boolean fair) - creates a reentrant lock with the given fairness policy. Passing true to fair results in a lock that uses a fair ordering policy, which means that under contention, the lock favors granting access to the longest-waiting thread.
- int getHoldCount()
- boolean isFair()
- boolean isHeldByCurrentThread()
Condition: Where Lock replaces synchronized methods and statements, Condition replaces Object monitor methods.
additionaly having multiple wait-sets per object, by combining them with the use of arbitrary Lock implementations.
Atomic variables
- Contended synchronization is expensive and throughput suffers as a result.A major reason for the expense is the frequent context switching that takes place; a context switch operation can take many processor cycles to complete.
- volatile variables only solve the visibility problem
java.util.concurrent.atomic offers classes for Boolean (AtomicBoolean), integer (AtomicInteger), long integer (AtomicLong) and reference (AtomicReference) types.
-----------------
- Java Synchronization protects data corruption on race conditions.
- spin lock (Busy wait) - overhead.
- Sleep lock - Context switching overhead.
- re-entrant mutual exclusion lock that extends the built-in monitor lock capabilities.
- Low overhead than ReentrantReadWriteLock
- improves performance when resource more often read than write.
- Provides more parallelism on multi core or multi processor hardware
- A non-negative integer that controls the access of multiple threads to a limited number of shared resources.
- Block thread until some conditions becomes true.
- Allow one or more thread to wait until s set of operation being performed in other threads complete.
ConditionObject(uses sleep locks) & Semaphore(uses busy waiting) big overhead than ReentrantLock&ReentrantReadWriteLock
Semaphore & ConditionObject are flexible and provides more capability.
------------------
reference ( javaworld )
Sqlite
- Open Source database
- supports relational database features like SQL syntax, transactions
- requires limited memory (approx. 250 KByte) which makes it a light weight database to embed in to each process
- supports the data types TEXT, INTEGER and REAL
Features:
- SQLite library and thus becomes an integral part of the application program.
- Due to the server-less design, SQLite applications require less configuration than client-server databases.
- SQLite is called zero-conf.
- The SQLite file format is cross-platform. A database file written on one machine can be copied to and used on a different machine with a different architecture.
- Adding new tables or new columns to existing tables is so easy.
- Content can be accessed and updated using powerful SQL queries.
- SQLite read operations can be multitasked, though writes can only be performed sequentially.
Design Tips:
First, Second and Third normal forms in Database (Students record)
1st - Remove duplicate data and break data in granular level
2nd - All column data should depend on full primar key and not part
3rd - No column should depend on other column
( ref : https://www.youtube.com/watch?v=wp0N1tYjEWc&feature=youtu.be&hd=1)
String Algorithms
Sorting
- Key indexed counting
- LSD (Least-significant-digit-first) string sorting
- Sorts equal length strings.
- uses key index counting method.
- MSD (Most-significant-digit-first) string sorting
- Recurvise sort
- Sorst any length strings
- 3-way radix sort
- R-way Tries
Friday, February 5, 2016
Android Performance
Battery Historian
1. Download Battery Historian from Github ( https://github.com/google/battery-historian)
2. from Terminal
- execute adb shell dumpsys batterystats --reset
Memory Monitor
1. In-built tool in android studio
Heap Viewer
Android Performance Case Study ( Source )
Android Adapter Good Practice ( Source )
Android String Placeholders ( Source )
StrictMode
1. Download Battery Historian from Github ( https://github.com/google/battery-historian)
2. from Terminal
- execute adb shell dumpsys batterystats --reset
Memory Monitor
1. In-built tool in android studio
Heap Viewer
Android Performance Case Study ( Source )
Android Adapter Good Practice ( Source )
Android String Placeholders ( Source )
StrictMode
Wednesday, February 3, 2016
Displaying Bitmaps Efficiently
Loading Large Bitmaps Efficiently
- Read Bitmap Dimensions and Type
- Use an AsyncTask
- Handle Concurrency ( when Bitmap is used in ListView, GridView )
Caching Bitmaps
Reference
1. developer.android.com
2. android-developers.blogspot ( Multithreading For Performance )
- Read Bitmap Dimensions and Type
- BitmapFactory ( decodeByteArray(), decodeFile(), decodeResource(), etc.)
- BitmapFactory.Options - Setting the inJustDecodeBounds property to true while decoding avoids memory allocation
- it’s not worth loading a higher pixel image into memory if it will eventually be displayed in a lower pixel thumbnail
- BitmapFactory.Options - use inSampleSize, To tell the decoder to subsample the image, loading a smaller version into memory
- Use an AsyncTask
- Handle Concurrency ( when Bitmap is used in ListView, GridView )
Caching Bitmaps
- Use a Memory Cache ( fast-loading UI can use memory and disk cache to quickly reload processed images )
- The LruCache class is well suited for Bitmap cacheing
- Keeps recently referenced objects in a strong referenced LinkedHashMap
- Evicts the least recently used member when cache memory exceeds its designated size.
Reference
1. developer.android.com
2. android-developers.blogspot ( Multithreading For Performance )
Subscribe to:
Posts (Atom)