Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Architecture Components - IT Step

Royce Mars
October 04, 2017

Architecture Components - IT Step

Talk about recommended Architecture by Google, some architecture patterns and about principle “be together, not the same” - and advices on how to apply Architecture Components to existing projects and with lovely tools

Royce Mars

October 04, 2017
Tweet

More Decks by Royce Mars

Other Decks in Programming

Transcript

  1. Architecture Components Constantine Mars Team Lead, Senior Developer @ DataArt

    Построение современной архитектуры мобильных приложений
  2. App-hopping OS may kill app at random time App components

    lifecycle is not under control Components should not depend on each other Can’t rely on data, stored in components There are Everyday Problems to Solve
  3. -Separation of concerns -Provide solid user experience -Keep UI lean

    and simple -Keep UI free of app logic -Drive UI from model -Use persistent model -Assign clear responsibilities for each model class Common Principles for staying in mind :)
  4. -Modular app -Each class responsible for one well-defined function -Should

    be no god objects -The app should be testable Remember Good Architecture Goals...
  5. “It is impossible to have one way of writing apps

    that will be the best for every scenario. That being said, this recommended architecture should be a good starting point for most use cases. If you already have a good way of writing Android apps, you don't need to change.” Be together. not the same
  6. Purpose: Display data and pass on UI events Neither contain

    the UI data, nor directly manipulate data Examples: Activity, Fragment Views = UI Controllers = LifecycleOwners
  7. After the lifecycles API in the Architecture Components becomes stable,

    the Fragment class in the Android Support Library will implement LifecycleOwner LifecycleActivity, LifecycleFragment
  8. ViewModel public class DetailActivityViewModel extends ViewModel { private WeatherEntry mWeather;

    public DetailActivityViewModel() {} public WeatherEntry getWeather() { return mWeather; } public void setWeather(WeatherEntry weatherEntry) { mWeather = weatherEntry; } }
  9. ViewModel and LifecycleOwner public class DetailActivity extends LifecycleActivity { DetailActivityViewModel

    viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... viewModel = ViewModelProviders.of(this).get(DetailActivityViewModel.class); } ...
  10. Represent data needed for the UI to display An observable

    data holder Lifecycle aware Automatic subscription management LiveData
  11. Live Data public class DetailActivityViewModel extends ViewModel { private MutableLiveData<WeatherEntry>

    mWeather; public DetailActivityViewModel() {} public MutableLiveData<WeatherEntry> getWeather() { return mWeather; } public void setWeather(WeatherEntry weatherEntry) { mWeather.postValue(weatherEntry); } }
  12. Live Data observing public class DetailActivity extends LifecycleActivity { DetailActivityViewModel

    viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... viewModel = ViewModelProviders.of(this).get(DetailActivityViewModel.class); viewModel.getWeather().observe(this, weatherEntry -> { if(weatherEntry!=null) { bindWeatherToUI(weatherEntry); } }); }
  13. -Single source of truth -ViewModels simply request data from the

    repository -Is a mediator between the different data sources Repository pattern Image from fernandocejas.com
  14. Manages data from a remote data source, such as the

    internet May use REST, Cloud Remote Network Data Source
  15. Each class in the diagram only stores a reference to

    the class or classes directly "below it" and not any classes above it Layered architecture pattern
  16. -Less boilerplate compared to the built-in APIs -Compile-time validation of

    SQL queries -Data observation via LiveData, RxJava Room ORM purposes
  17. @Entity declaration @Entity(tableName = "weather", indices = {@Index(value = {"date"},

    unique = true)}) public class WeatherEntry { @PrimaryKey(autoGenerate = true) private int id; … }
  18. @Entity constructors //Room constructor public WeatherEntry(int id, int weatherIconId, Date

    date, ...) { //Json constructor - ignored by Room @Ignore public WeatherEntry(int weatherIconId, Date date, // (!) Only one constructor should be exposed to Room ...
  19. Dao

  20. @Dao declaration @Dao public interface WeatherDao { @Query("SELECT * FROM

    weather") List<WeatherEntry> getAll(); @Insert(onConflict = OnConflictStrategy.REPLACE) void insertAll(WeatherEntry... weatherEntries); @Delete void delete(WeatherEntry weatherEntry); }
  21. @Database declaration @Database(entities = {WeatherEntry.class}, version = 1) @TypeConverters(DateConverter.class) public

    abstract class AppDatabase extends RoomDatabase { public abstract WeatherDao weatherDao(); }
  22. @Database - a singleton private static final String DATABASE_NAME =

    "weather"; private static final Object LOCK = new Object(); private static volatile AppDatabase sInstance; public static AppDatabase getInstance(Context context) { if (sInstance == null) { synchronized (LOCK) { if (sInstance == null) { sInstance = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, AppDatabase.DATABASE_NAME).build(); } }} return sInstance; }
  23. Type converters class DateConverter { @TypeConverter public static Date toDate(Long

    timestamp) { return timestamp == null ? null : new Date(timestamp); } @TypeConverter public static Long toTimestamp(Date date) { return date == null ? null : date.getTime(); } }
  24. Repository pattern public class WeatherRepository { public synchronized static WeatherRepository

    getInstance(); public synchronized void initializeData(); private void deleteOldData(); private boolean isFetchNeeded(); private void startFetchWeatherService(); }
  25. Repository - fetch data from network mWeatherNetworkDataSource = weatherNetworkDataSource; LiveData<WeatherEntry[]>

    networkData = mWeatherNetworkDataSource.getCurrentWeatherForecasts(); networkData.observeForever(newForecastsFromNetwork -> { mExecutors.diskIO().execute(() -> { mWeatherDao.bulkInsert(newForecastsFromNetwork); Log.d(LOG_TAG, "New values inserted"); }); });
  26. Repository - use LiveData private WeatherNetworkDataSource(Context context, AppExecutors executors) {

    mContext = context; mExecutors = executors; mDownloadedWeatherForecasts = new MutableLiveData<WeatherEntry[]>(); }
  27. Check when to fetch private boolean isFetchNeeded() { Date today

    = CustomDateUtils.getNormalizedUtcDateForToday(); int count = mWeatherDao.countAllFutureWeather(today); return (count < WeatherNetworkDataSource.NUM_DAYS); }
  28. Check when to fetch public synchronized void initializeData() { if

    (mInitialized) return; mInitialized = true; mExecutors.diskIO().execute(() -> { if (isFetchNeeded()) { startFetchWeatherService(); } }); }
  29. And again - observe LiveData public class DetailActivity extends LifecycleActivity

    { DetailActivityViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... viewModel = ViewModelProviders.of(this).get(DetailActivityViewModel.class); viewModel.getWeather().observe(this, weatherEntry -> { if(weatherEntry!=null) { bindWeatherToUI(weatherEntry); } }); }
  30. What if... I use RxJava? I already have MVP? I

    love Kotlin? I’m working on legacy project? Typical questions
  31. Guide to App Architecture https://developer.android.com/topic/libraries/architecture/guide.html Architecture Components https://developer.android.com/topic/libraries/architecture/index.html I/O ‘17

    Architecture Components Introduction - https://youtu.be/FrteWKKVyzI Solving the Lifecycle Problem - https://youtu.be/bEKNi1JOrNs Persistence and Offline - https://youtu.be/MfHsPGQ6bgE Architecture Components on GDD Europe - https://youtu.be/Ts-uxYiBEQ8 GDD Europe CodeLabs g.co/codelabs/gdd17 Google Github samples https://github.com/googlesamples/android-architecture-components What to read and watch :)
  32. Moxy https://github.com/Arello-Mobile/Moxy Mosby https://github.com/sockeqwe/mosby Android MVP Helper https://github.com/Ufkoku/AndroidMVPHelper Clean Architecture

    https://github.com/android10/Android-CleanArchitecture Reark https://github.com/reark/reark MVP + Dagger2 + Rx https://android.jlelse.eu/mvp-dagger-2-rx-clean-modern-android-app-code-74f63c9a6f2f Architecture the Lost Years by Uncle Bob https://youtu.be/WpkDN78P884 Alternatives to consider