android’development bestpracces% - · pdf fileandroid’101 •...
TRANSCRIPT
![Page 1: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/1.jpg)
Android development Best Prac*ces
Ivan Gavran, Calyx d.o.o.
![Page 2: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/2.jpg)
Overview
• Android 101 • Adap:ve UI • Offline support • Networking :ps • Handling bitmaps efficiently • Conclusion
![Page 3: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/3.jpg)
Android 101
• Applica:on Components – Ac:vi:es/Fragments – Service – Content Providers – Broadcast Receivers
• Component Ac:va:on – Intents – Intent Filters
![Page 4: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/4.jpg)
Android 101
• The Manifest File – Component declara:on – Component capabili:es – Applica:on Requirements
• Applica:on Resources – Images, audios, videos – Layouts – Strings, dimensions...
![Page 5: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/5.jpg)
The Good Parts
• Separa:on of concerns – Sources – Resources – App configura:on
• Inter-‐process communica:on – Intents, Content Providers
• Built in services – Loca:on, No:fica:on, Connec:vity...
![Page 6: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/6.jpg)
Case study
• Android app backed by a REST Service • Requirements: – Adap:ve UI – Offline support – Efficiency
![Page 7: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/7.jpg)
Lesson 1: Define adap:ve UI
![Page 8: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/8.jpg)
Adap:ve Ac:onbar
Adap:ve GridView
![Page 9: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/9.jpg)
Adap:ve Ac:onbar
Adap:ve Layout
![Page 10: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/10.jpg)
Power of resources <resources>! <item name="restaurant_layout" type="layout"> ! @layout/restaurant_details! </item>!
<bool name="has_two_panes">false</bool>!</resources>!
res/values/layouts.xml
<resources>! <item name="restaurant_layout" type="layout"> ! @layout/restaurant_details_land! </item>!
<bool name="has_two_panes">true</bool>!</resources>!
res/values-‐land/layouts.xml
![Page 11: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/11.jpg)
!public class MyActivity extends FragmentActivity {!!
@Override!public void onCreate(Bundle savedInstanceState) {!
!super.onCreate(savedInstanceState);!!
!//Set content view based on layout defined !!// for current screen configuration !!
!setContentView(R.layout.activity_restaurant_layout);!!!!// or read any other value...!!if(getResources().getBoolean(R.bool.has_two_panes)){!! !//... we are in landscape!!!}!
}!
Ac:vity ini:aliza:on
![Page 12: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/12.jpg)
Lesson 2: Use Loaders for loading data in an
ac:vity or fragment
![Page 13: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/13.jpg)
The naive approach MyAc:vity
AsyncTask REST client
class MyActivity extends Activity {!! @Override! public void onCreate(...) {! new MyAsyncTask().execute(...);! }!!}!
class MyAsyncTask extends !!AsyncTask<Pars, Progress, Res>{!
! void onPreExecute(Pars...){! // executed on UI thread! }! Res doInBackground(){! // executed on background thread! }! void onPostExecute(Res){! // executed on UI thread! }!}!
![Page 14: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/14.jpg)
Problems with AsyncTasks
• Ac:vity life cycle • Memory Leaks
![Page 15: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/15.jpg)
MyAc:vity implements
LoaderCallbacks Loader REST
client LoaderManager
android.app.LoaderManager!!android.app.LoaderManager.LoaderCallbacks!!android.content.Loader<D>!! ↳ android.content.AsyncTaskLoader<D>!
! ! ↳ android.content.CursorLoader!
Loader API
![Page 16: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/16.jpg)
!public class MyActivity extends FragmentActivity !implements LoaderManager.LoaderCallbacks<DomainModel> {!
!@Override!public void onCreate(Bundle savedInstanceState) {!
!super.onCreate(savedInstanceState);!!//... activity setup code!!!
!getLoaderManager().initLoader (0, null, this);!}!
Loader ini:aliza:on
![Page 17: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/17.jpg)
!public class MyActivity extends FragmentActivity !implements LoaderManager.LoaderCallbacks<DomainModel> {!
!//....!public Loader<DomainModel> onCreateLoader(int id, Bundle args) {!
!return new MyCursorLoader(this);!}!!
public void onLoadFinished(Loader<DomainModel> loader,!!DomainModel data) {!!!!mAdapter.swapCursor(data);!
}!!
public void onLoaderReset(Loader<DomainModel> loader) {!!mAdapter.swapCursor(null);!
}!
LoaderCallbacks interface implementa:on
![Page 18: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/18.jpg)
!public class MyLoader extends AsyncTaskLoader<DomainModel> {!!
!public MyCursorLoader (Context context) {!! !super(context);!!}!!@Override!!protected void onStartLoading() {!! !forceLoad();!
!}!!@Override!!public DomainModel loadInBackground() {!! !return RestClient.get().getDomainModel();!!}!!@Override!
!protected void onReset() {!! !super.onReset();!!}!
Loader implementa:on
![Page 19: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/19.jpg)
Goals
Adap:ve UI
Offline support
Efficiency
![Page 20: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/20.jpg)
Lesson 3: Local Database and Sync Service
![Page 21: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/21.jpg)
REST Client SyncService
SqLite DB
Ac:vity Ac:vity Ac:vity
Loader Loader Loader
Applica:on architecture
![Page 22: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/22.jpg)
!public class SyncService extends IntentService {!!
!public SyncService() {!! !super("DataSyncService");!!}!!!!@Override!!protected void onHandleIntent(Intent intent) {!! !String action = intent.getAction();!
!! !// get optional sync parameters from the intent!
!! !doSync(...);!!}!
Synchroniza:on IntentService
![Page 23: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/23.jpg)
How to refresh data in the applica:on
• Start sync service – Just start service from any part of the applica:on
• Restart Loaders – implement BroadcastReceiver in each Loader
• Refresh UI – triggered by Loaders!
![Page 24: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/24.jpg)
!public class MyCursorLoader extends AsyncTaskLoader<Cursor> {!!
!//...!!
!private static class SyncIntentReceiver extends BroadcastReceiver {!! !final MyReservationsCursorLoader mLoader;!! !public SyncIntentReceiver(MyReservationsCursorLoader loader) {!! ! !mLoader = loader;!
! ! !IntentFilter filter = new IntentFilter(!! ! ! ! !MyAppConstants.ACTION_SYNC_FINISHED);!! ! !mLoader.getContext().registerReceiver(this, filter);!! !}!
!! !@Override!
! !public void onReceive(Context context, Intent intent) {!! ! !mLoader.onContentChanged();!! !}!!}!
!
SyncIntentReciever
![Page 25: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/25.jpg)
public class MyCursorLoader extends AsyncTaskLoader<Cursor> {!!private SyncIntentReceiver mObserver; !!@Override!
!protected void onStartLoading() {!! !if (mObserver == null) {!! ! !mObserver = new SyncIntentReceiver(this);!! !}!! !forceLoad();!!}!
!@Override!!protected void onReset() {!! !super.onReset();!! !if (mObserver != null) {!! ! !getContext().unregisterReceiver(mObserver);!! ! !mObserver = null;!
! !}!!}!!private static class SyncIntentReceiver extends BroadcastReceiver {!! !//...!!}!
}!!
SyncIntentReceiver
![Page 26: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/26.jpg)
Result • Loose coupling of applica:on and synchroniza:on logic • Easy implementa:on of applica:on specific sync strategies
– Update triggered by app user
– Updates based on changes on the applica:on server
– Loca:on based updates
– ... just start the Sync Service...
![Page 27: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/27.jpg)
Goals
Adap:ve UI
Offline support
Efficiency
![Page 28: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/28.jpg)
Lesson 4: Keep mobile data in sync with the
applica:on server
![Page 29: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/29.jpg)
Objec:ves • Be efficient:
– Data traffic costs
– Ba`ery life
• Be invisible – Don't keep user wait
– Give users what they want before they have to ask for it
Applica:on Server
Mobile device
Mobile device
Web app
![Page 30: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/30.jpg)
Networking :ps • Detect ac:ve network type
– WIFI vs. cellular data
– Mobile radio state machine
• Networking over 3G networks – Avoid periodical data transfer – don't pull for updates
– Use greedy loading but don't be too greedy
– Prefetching, bundling
• Google Cloud Messaging – Push data to mobile device
![Page 31: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/31.jpg)
The mobile radio state machine
Radio Standby Radio Low Power
Radio Full Power
2s latency
1.5s latency
Radio idle for ~5-‐10 seconds
Radio idle for ~10-‐60 seconds
![Page 32: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/32.jpg)
Google Cloud Messaging
Applica:on Server
Mobile device
GCM service
1
2
3
Register device
registra:on Id
registra:on Id
A
registra:onId + Message
B Message
![Page 33: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/33.jpg)
Lesson 5: Displaying Bitmaps Efficiently
![Page 34: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/34.jpg)
Resize your images on the server.
![Page 35: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/35.jpg)
Load Large Bitmaps Efficiently
Image resolu?on Bitmap size (ARGB_8888)
2048*1536 12 MB
512*384 0.75 MB
128*96 0.05
![Page 36: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/36.jpg)
public static Bitmap decodeSampledBitmap(InputStream is, int reqWidth, int reqHeight) {!! // First decode with inJustDecodeBounds=true to check dimensions! final BitmapFactory.Options options = new BitmapFactory.Options();!
options.inJustDecodeBounds = true;! BitmapFactory.decodeStream(is, null, options);!! // Calculate inSampleSize! options.inSampleSize = calculateInSampleSize(!
! !options.outWidth, options.outHeight, reqWidth, reqHeight);!
! // Decode bitmap with inSampleSize set! options.inJustDecodeBounds = false;! return BitmapFactory.decodeStream(is, null, options);!}!
Decode Large Bitmaps
![Page 37: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/37.jpg)
Process Bitmaps off the UI thread.
![Page 38: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/38.jpg)
class BitmapLoaderTask extends AsyncTask<String, Void, Bitmap> {! private final WeakReference<ImageView> imageViewReference;! public BitmapWorkerTask(ImageView imageView) {!
! !imageViewReference = new WeakReference<ImageView>(imageView);! }!
!@Override!!protected Bitmap doInBackground(String... params) {!! !String url = params[0];!! !InputStream is = ImageLoader.load(url);!
! !return decodeSampledBitmap(is, 100, 100));! }!
!@Override!!protected void onPostExecute(Bitmap bitmap) {!
if (imageViewReference != null && bitmap != null) {! final ImageView imageView = imageViewReference.get();!
if (imageView != null) {! imageView.setImageBitmap(bitmap);! }! }! }!}!
Processing Bitmaps Off the UI Thread
![Page 39: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/39.jpg)
Caching Bitmaps
![Page 40: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/40.jpg)
private LruCache<String, Bitmap> mMemoryCache;!!@Override!
protected void onCreate(Bundle savedInstanceState) {!!
!final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);!!
!// Use 1/8th of the available memory for this memory cache.! !final int cacheSize = maxMemory / 8;!
! !mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {! @Override! protected int sizeOf(String key, Bitmap bitmap) {! // The cache size will be measured in kilobytes rather than! // number of items.!
return bitmap.getByteCount() / 1024;! }! };! ...!}!
Caching Bitmaps using LruCache
![Page 41: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/41.jpg)
class RetFragment extends Fragment {! !
!private static final String TAG = "RetFragment";!
!public LruCache<String, Bitmap> mRetainedCache;!!
!public static RetFragment getInstance(FragmentManager fm) {! RetFragment fragment = (RetFragment) fm.findFragmentByTag(TAG);! if (fragment == null) {! fragment = new RetFragment();!
}! return fragment;! }!! @Override! public void onCreate(Bundle savedInstanceState) {!
super.onCreate(savedInstanceState);! setRetainInstance(true);! }!}!
Retaining Cached Bitmaps between orienta:on changes
![Page 42: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/42.jpg)
Goals
Adap:ve UI
Offline support
Efficiency
![Page 43: Android’development BestPracces% - · PDF fileAndroid’101 • The’ManifestFile’ – Componentdeclaraon’ – Componentcapabili:es’ – Applicaon’Requirements’ • Applicaon’Resources’](https://reader033.vdocuments.site/reader033/viewer/2022051721/5a79bfde7f8b9ad7608c226c/html5/thumbnails/43.jpg)
Conclusion
• Support different devices
• Be invisible
• Be efficient
• Be reliable