ã¿ãªããããã«ã¡ã¯ã ååã®Google I / Oã§ãã€ãã«Androidã¢ããªã±ãŒã·ã§ã³ã®ã¢ãŒããã¯ãã£ã«é¢ããGoogleã®å
¬åŒããžã§ã³ãšããã®å®è£
ã®ããã®ã©ã€ãã©ãªãçºè¡šããŸããã 10幎ãçµã£ãŠããŸããã ãã¡ãããç§ã¯ããã«ããã§æäŸããããã®ã詊ããŠã¿ããã£ãã§ãã
泚æïŒã©ã€ãã©ãªã¯ã¢ã«ãã¡çã§ãããããäºææ§ã«åœ±é¿ãã倿Žãäºæ³ãããŸãã
ã©ã€ããµã€ã¯ã«
æ°ããã¢ãŒããã¯ãã£ã®äž»ãªã¢ã€ãã¢ã¯ãã¢ã¯ãã£ããã£ãšãã©ã°ã¡ã³ãããããžãã¯ãæå€§éã«åé€ããããšã§ãã äŒç€Ÿã¯ããããã®ã³ã³ããŒãã³ããã·ã¹ãã ã«å±ããéçºè
ã®è²¬ä»»ç¯å²ã«å±ããŠããªããšèŠãªãã¹ãã ãšäž»åŒµããŠããŸãã ã¢ã€ãã¢èªäœã¯æ°ãããã®ã§ã¯ãªããMVP / MVVPã¯çŸåšã¢ã¯ãã£ãã«äœ¿çšãããŠããŸãã ãã ããã³ã³ããŒãã³ãã®ã©ã€ããµã€ã¯ã«ãšã®é¢ä¿ã¯åžžã«éçºè
ã®è¯å¿ã«ãšã©ãŸã£ãŠããŸãã
ããã¯ããã§ã¯ãããŸããã ã¯ã©ã¹Lifecycle ã LifecycleActivity ã LifecycleFragmentãå«ãæ°ããããã±ãŒãžandroid.arch.lifecycleãæç€ºãããŸãã è¿ãå°æ¥ã LifecycleOwnerã€ã³ã¿ãŒãã§ãŒã¹ã®å®è£
ãéããŠãç¹å®ã®ã©ã€ããµã€ã¯ã«ã«ååšããã·ã¹ãã ã®ãã¹ãŠã®ã³ã³ããŒãã³ããã©ã€ããµã€ã¯ã«ãæäŸãããšæ³å®ãããŠããŸãã
public interface LifecycleOwner { Lifecycle getLifecycle(); }
ããã±ãŒãžã¯ãŸã ã¢ã«ãã¡çã§ãããAPIãå®å®çãšæ··åã§ããªããããLifecycleActivityããã³LifecycleFragmentã¯ã©ã¹ã远å ãããŸããã ããã±ãŒãžãå®å®ããç¶æ
ã«ãªããšãLifecycleOwnerã¯Fragmentããã³AppCompatActivityã«å®è£
ãããLifecycleActivityããã³LifecycleFragmentã¯åé€ãããŸãã
ã©ã€ããµã€ã¯ã«ã«ã¯ãã³ã³ããŒãã³ãã®ã©ã€ããµã€ã¯ã«ã®çŸåšã®ç¶æ
ãå«ãŸããŠãããLifecycleObserverãã©ã€ããµã€ã¯ã«é·ç§»ã€ãã³ãã«ãµãã¹ã¯ã©ã€ãã§ããããã«ããŸãã è¯ãäŸïŒ
class MyLocationListener implements LifecycleObserver { private boolean enabled = false; private final Lifecycle lifecycle; public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) { this.lifecycle = lifecycle; this.lifecycle.addObserver(this);
ããšã¯ãMyLocationListenerãäœæããŠããããå¿ããã ãã§ãã
class MyActivity extends LifecycleActivity { private MyLocationListener locationListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); locationListener = new MyLocationListener(this, this.getLifecycle(), location -> {
ã©ã€ãããŒã¿
LiveDataã¯rxJavaã®Observableã«é¡äŒŒããŠããŸãããã©ã€ããµã€ã¯ã«ã®ååšãèªèããŠããŸãã LiveDataã«ã¯å€ãå«ãŸããŠããããã®å倿Žã¯ãªãã¶ãŒããŒã«éãããŸãã
LiveDataã®3ã€ã®äž»èŠãªã¡ãœããïŒ
setValueïŒïŒ-å€ã倿Žãããªãã¶ãŒããŒã«éç¥ããŸã;
onActiveïŒïŒ-å°ãªããšã1人ã®ã¢ã¯ãã£ããªãªãã¶ãŒããŒãçŸããŸããã
onInactiveïŒïŒ-ã¢ã¯ãã£ããªãªãã¶ãŒãã¯ãã以äžãããŸããã
ãããã£ãŠãLiveDataã«ã¢ã¯ãã£ããªãªãã¶ãŒããŒããªãå ŽåãããŒã¿ã®æŽæ°ã忢ã§ããŸãã
ã¢ã¯ãã£ããªãªãã¶ãŒããŒãšã¯ãã©ã€ããµã€ã¯ã«ãSTARTEDãŸãã¯RESUMEDç¶æ
ã«ãããªãã¶ãŒããŒã§ãã æ°ããã¢ã¯ãã£ããªãªãã¶ãŒããŒãLiveDataã«åå ãããšãããã«çŸåšã®å€ãååŸãããŸãã
ããã«ãããLiveDataã€ã³ã¹ã¿ã³ã¹ãéç倿°ã«ä¿åããUIã³ã³ããŒãã³ããããµãã¹ã¯ã©ã€ãã§ããŸãã
public class LocationLiveData extends LiveData<Location> { private LocationManager locationManager; private SimpleLocationListener listener = new SimpleLocationListener() { @Override public void onLocationChanged(Location location) { setValue(location); } }; public LocationLiveData(Context context) { locationManager = (LocationManager) context.getSystemService( Context.LOCATION_SERVICE); } @Override protected void onActive() { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener); } @Override protected void onInactive() { locationManager.removeUpdates(listener); } }
éåžžã®éç倿°ãäœæããŸãããïŒ
public final class App extends Application { private static LiveData<Location> locationLiveData = new LocationLiveData(); public static LiveData<Location> getLocationLiveData() { return locationLiveData; } }
ãŸããããšãã°ã2ã€ã®ã¢ã¯ãã£ããã£ã§å Žæã®å€æŽããµãã¹ã¯ã©ã€ãããŸãã
public class Activity1 extends LifecycleActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity1); getApplication().getLocationLiveData().observe(this, (location) -> {
observeã¡ãœããã¯LifecycleOwnerãæåã®ãã©ã¡ãŒã¿ãŒãšããŠäœ¿çšãããããåãµãã¹ã¯ãªãã·ã§ã³ãç¹å®ã®ã¢ã¯ãã£ããã£ã®ã©ã€ããµã€ã¯ã«ã«ãªã³ã¯ããããšã«æ³šæããŠãã ããã
ã¢ã¯ãã£ããã£ã®ã©ã€ããµã€ã¯ã«ãDESTROYEDãµãã¹ã¯ãªãã·ã§ã³ã«å
¥ããšããã«ç Žæ£ãããŸãã
ãã®ã¢ãããŒãã®å©ç¹ã¯ãã³ãŒãããã¹ãã²ããã£ãçºçããããšã¯ãªããã¡ã¢ãªãªãŒã¯ãçºçããªãããšãšã匷å¶çµäºãããã¢ã¯ãã£ããã£ã§ãã³ãã©ãŒãåŒã³åºãããªãããšã§ãã
ViewModel
ViewModelã¯ãUIã®ããŒã¿ãŠã§ã¢ããŠã¹ã§ãããããšãã°æ§æã®å€æŽãªã©ã®UIã³ã³ããŒãã³ãã®ç Žå£ã«èããããšãã§ããŸãïŒã¯ããMVVMã¯çŸåšãå
¬åŒã«æšå¥šããããã©ãã€ã ã§ãïŒã æ°ããäœæãããã¢ã¯ãã£ããã£ã¯ã以åã«äœæãããã¢ãã«ã«åæ¥ç¶ããŸãã
public class MyActivityViewModel extends ViewModel { private final MutableLiveData<String> valueLiveData = new MutableLiveData<>(); public LiveData<String> getValueLiveData() { return valueLiveData; } } public class MyActivity extends LifecycleActivity { MyActivityViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity); viewModel = ViewModelProviders.of(this).get(MyActivityViewModel.class); viewModel.getValueLiveData().observe(this, (value) -> {
ofã¡ãœãããã©ã¡ãŒã¿ãŒã¯ãã¢ãã«ã€ã³ã¹ã¿ã³ã¹ã®ã¹ã³ãŒããå®çŸ©ããŸãã ã€ãŸããåãå€ãofã«æž¡ããããšãã¯ã©ã¹ã®åãã€ã³ã¹ã¿ã³ã¹ãè¿ãããŸãã ã€ã³ã¹ã¿ã³ã¹ããŸã ãªãå Žåã¯äœæãããŸãã
ã¹ã³ãŒããšããŠã¯ãèªåèªèº«ãžã®ãªã³ã¯ã ãã§ãªãããã£ãšsomethingãªãã®ãæž¡ãããšãã§ããŸãã çŸåšã3ã€ã®ã¢ãããŒããæšå¥šãããŠããŸãã
- ã¢ã¯ãã£ããã£èªäœã転éãããŸãã
- ãã©ã°ã¡ã³ãã¯ããèªäœãäŒããŸãã
- ãã©ã°ã¡ã³ãã¯ãã®ã¢ã¯ãã£ããã£ã転éããŸãã
3çªç®ã®æ¹æ³ã§ã¯ãå
±éã®ViewModelãä»ããŠãã©ã°ã¡ã³ããšãã®ã¢ã¯ãã£ããã£éã®ããŒã¿è»¢éãæŽçã§ããŸãã ã€ãŸãããã©ã°ã¡ã³ãã®åŒæ°ãã¢ã¯ãã£ããã£çšã®ç¹å¥ãªã€ã³ã¿ãŒãã§ã€ã¹ãäœæããå¿
èŠããªããªããŸããã 誰ããäºãã«ã€ããŠäœãç¥ããªãã
ã¢ãã«ã€ã³ã¹ã¿ã³ã¹ããã€ã³ããããŠãããã¹ãŠã®ã³ã³ããŒãã³ããç Žæ£ãããšããã®ã€ã³ã¹ã¿ã³ã¹ã«å¯ŸããŠonClearedã€ãã³ããçºçããã¢ãã«ãç Žæ£ãããŸãã
éèŠãªç¹ïŒViewModelã¯éåžžãåãã¢ãã«ã€ã³ã¹ã¿ã³ã¹ã䜿çšããã³ã³ããŒãã³ãã®æ°ãç¥ããªããããã¢ãã«å
ã®ã³ã³ããŒãã³ããžã®åç
§ãä¿åããããšã¯ãããŸããã
ã«ãŒã æ°žç¶ã©ã€ãã©ãª
ç§ãã¡ã®å¹žçŠã¯ãã¢ããªã±ãŒã·ã§ã³ã®æ©ãããçµäºåŸã«ããŒã¿ãããŒã«ã«ã«ä¿åããèœåããªããã°äžå®å
šã§ãã ããã§ã¯ãSQLiteãã¢ã¯ã»ã¹å¯èœãªãç®±ããåºããŠãããã«å©ããæ±ããŠããŸãã ãã ããäž»ã«ã³ã³ãã€ã«æã«ã³ãŒãããã§ãã¯ããæ¹æ³ãæäŸããªããããããŒã¿ããŒã¹APIã¯ããªãäžäŸ¿ã§ãã ã¢ããªã±ãŒã·ã§ã³ã®å®è¡æã«SQLåŒã®ã¿ã€ããã¹ã«ã€ããŠæ¢ã«åŠç¿ããŠãããã¯ã©ã€ã¢ã³ãã§ã¯ãªããšããŠãããã§ãã
ããããããã¯éå»ã®ãã®ã§ããGoogleã¯ãã³ã³ãã€ã«äžã«SQLåŒã®éçåæãè¡ãORMã©ã€ãã©ãªãå°å
¥ããŸããã
Entity ã DAO ãããã³Databaseã®å°ãªããšã3ã€ã®ã³ã³ããŒãã³ããå®è£
ããå¿
èŠããããŸã ã
ãšã³ãã£ãã£ã¯ãããŒãã«å
ã®1ã€ã®ãšã³ããªã§ãã
@Entity(tableName = «users») public class User() { @PrimaryKey public int userId; public String userName; }
DAOïŒããŒã¿ã¢ã¯ã»ã¹ãªããžã§ã¯ãïŒ-ç¹å®ã®ã¿ã€ãã®ã¬ã³ãŒãã®åŠçãã«ãã»ã«åããã¯ã©ã¹ïŒ
@Dao public interface UserDAO { @Insert(onConflict = REPLACE) public void insertUser(User user); @Insert(onConflict = REPLACE) public void insertUsers(User⊠users); @Delete public void deleteUsers(User⊠users); @Query(«SELECT * FROM users») public LiveData<List<User>> getAllUsers(); @Query(«SELECT * FROM users WHERE userId = :userId LIMIT 1») LiveData<User> load(int userId); @Query(«SELECT userName FROM users WHERE userId = :userId LIMIT 1») LiveData<String> loadUserName(int userId); }
DAOã¯ã€ã³ã¿ãŒãã§ã€ã¹ã§ãããã¯ã©ã¹ã§ã¯ãªãããšã«æ³šæããŠãã ããã ãã®å®è£
ã¯ã³ã³ãã€ã«äžã«çæãããŸãã
ç§ã®æèŠã§ã¯ãæãé©ãã¹ãããšã¯ãååšããªãããŒãã«ãšãã£ãŒã«ããåç
§ããåŒãQueryã«æž¡ããããšã³ã³ãã€ã«ãã¯ã©ãã·ã¥ããããšã§ãã
ã¯ãšãªã«ã¯ãããŒãã«çµåãåŒãšããŠå«ããããšãã§ããŸãã ãã ãããšã³ãã£ãã£èªäœã«ã¯ä»ã®ããŒãã«ãžã®ãªã³ã¯ãå«ããããšã¯ã§ããŸãããããã¯ããããã«ã¢ã¯ã»ã¹ããéã®é
å»¶ããŒã¿ã®èªã¿èŸŒã¿ãåãã¹ããªãŒã ã§éå§ãããããããUIã¹ããªãŒã ã«ãªãããã§ãã ãããã£ãŠãGoogleã¯ãã®ãããªæ
£è¡ãå®å
šã«çŠæ¢ããããšã決å®ããŸããã
ãŸããã³ãŒããããŒãã«ã®ãšã³ããªã倿Žãããšããã«ããã®ããŒãã«ãå«ããã¹ãŠã®LiveDataãæŽæ°ãããããŒã¿ããªãã¶ãŒããŒã«è»¢éããããšãéèŠã§ãã ã€ãŸããã¢ããªã±ãŒã·ã§ã³ã®ããŒã¿ããŒã¹ã¯ã究極ã®çå®ãã«ãªããŸããã ãã®ã¢ãããŒãã«ãããã¢ããªã±ãŒã·ã§ã³ã®ããŸããŸãªéšåã®ããŒã¿ã®äžæŽåãæçµçã«åãé€ãããšãã§ããŸãã
ããã ãã§ãªããGoogleã¯å°æ¥ã倿Žã1è¡ããšã«è¿œè·¡ããçŸåšã®ããã«è¡šåœ¢åŒã§ã¯è¿œè·¡ããªãããšãçŽæããŸãã
æåŸã«ãããŒã¿ããŒã¹èªäœãæå®ããå¿
èŠããããŸãã
@Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDAO userDao(); }
ããã§ã¯ã³ãŒãçæã䜿çšããããããã¯ã©ã¹ã§ã¯ãªãã€ã³ã¿ãŒãã§ã€ã¹ãèšè¿°ããŠããŸãã
Applicationã¯ã©ã¹ãŸãã¯Daggerã¢ãžã¥ãŒã«ã§ã·ã³ã°ã«ãã³ããŒã¿ããŒã¹ãäœæããŸãã
AppDatabase database = Room.databaseBuilder(context, AppDatabase.class, "data").build();
ç§ãã¡ã¯ããããDAOãååŸããããªãã¯åãããšãã§ããŸãïŒ
database.userDao().insertUser(new User(âŠ));
DAOã¡ãœããã®æåã®åŒã³åºãã§ãæå®ãããŠããå ŽåãããŒãã«ãèªåçã«äœæ/åäœæãããããã¹ããŒããæŽæ°ããããã®SQLã¹ã¯ãªãããå®è¡ãããŸãã ã¹ããŒãæŽæ°ã¹ã¯ãªããã¯ãç§»è¡ãªããžã§ã¯ããä»ããŠæå®ãããŸãã
AppDatabase database = Room.databaseBuilder(context, AppDatabase.class, "data") .addMigration(MIGRATION_1_2) .addMigration(MIGRATION_2_3) .build(); static Migration MIGRATION_1_2 = new Migration(1, 2) { @Override public void migrate(SupportSQLDatabase database) { database.execSQL(âŠ); } } static Migration MIGRATION_2_3 = new Migration(2, 3) { ⊠}
ããã«ãAppDatabaseã§æ³šéã®ã¹ããŒã ã®çŸåšã®ããŒãžã§ã³ã瀺ãããšãå¿ããªãã§ãã ããã
ãã¡ãããã¹ããŒããæŽæ°ããããã®SQLã¹ã¯ãªããã¯åãªãæååã§ããå¿
èŠãããããã°ãããããšããŒãã«ã¯ã©ã¹ã倧å¹
ã«å€æŽããããããå€éšå®æ°ã«äŸåããªãã§ãã ãããå€ãããŒãžã§ã³ã®ããŒã¿ããŒã¹ã®æŽæ°ã¯ãšã©ãŒãªãã§å®è¡ããå¿
èŠããããŸãã
ãã¹ãŠã®ã¹ã¯ãªããã®å®è¡ãçµäºãããšãããŒã¹ã¯ã©ã¹ãšãšã³ãã£ãã£ã¯ã©ã¹ã®ã³ã³ãã©ã€ã¢ã³ã¹ã®èªåãã§ãã¯ãå®è¡ãããäžäžèŽãããå Žåã¯äŸå€ãã¹ããŒãããŸãã
泚æïŒå®éã®ããŒãžã§ã³ããææ°ããŒãžã§ã³ãžã®ç§»è¡ã®ãã§ãŒã³ãäœæã§ããªãã£ãå ŽåãããŒã¿ããŒã¹ã¯åé€ãããåäœæãããŸãã
ç§ã®æèŠã§ã¯ãã¹ããŒã æŽæ°ã¢ã«ãŽãªãºã ã«ã¯æ¬ ç¹ããããŸãã ã䜿ãã®ããã€ã¹ã«å€ãããŒã¿ããŒã¹ãããå ŽåãããŒã¿ããŒã¹ã¯æŽæ°ãããŸããããã¹ãŠåé¡ãããŸããã ãã ããããŒã¿ããŒã¹ããªããå¿
èŠãªããŒãžã§ã³ã1以äžã§ãç§»è¡ã®ã»ãããæå®ãããŠããå ŽåãããŒã¿ããŒã¹ã¯ãšã³ãã£ãã£ã«åºã¥ããŠäœæãããç§»è¡ã¯å®è¡ãããŸããã
ç§»è¡ã§ã¯ãããŒãã«ã®æ§é ã倿Žããããšããã§ããŸããããããŒãã«ãããŒã¿ã§åããããšã¯ã§ããŸããã ããã¯æ®å¿µã§ãã ãã®ã¢ã«ãŽãªãºã ã®æ¹åãæåŸ
ã§ãããšæããŸãã
ããããªå»ºç¯
äžèšã®ãã¹ãŠã®ãšã³ãã£ãã£ã¯ãææ¡ãããŠããæ°ããã¢ããªã±ãŒã·ã§ã³ã¢ãŒããã¯ãã£ã®ããªãã¯ã§ãã Googleã¯ã©ãã«ãããããªã¢ãŒããã¯ãã£ãæžããŠããªãããšã«æ³šæããŠãã ãããããã¯ç§ã®åŽããã®ããã€ãã®èªç±ã§ãããèãæ¹ã¯äŒŒãŠããŸãã

ãšã³ãã£ãã£ã¯ããããäžã®ãšã³ãã£ãã£ã«ã€ããŠäœãç¥ããŸããã
ã¢ãã«ãšãªã¢ãŒãããŒã¿ãœãŒã¹ã¯ãããããããŒã¿ãããŒã«ã«ã«ä¿åãããããã¯ãŒã¯çµç±ã§ã¯ãšãªãå®è¡ããŸãã ãªããžããªã¯ããã£ãã·ã¥ã管çããããžãã¹ç®æšã«åŸã£ãŠåã
ã®ãšã³ãã£ãã£ãçµ±åããŸãã ãªããžããªã¯ã©ã¹ã¯ãéçºè
ã«ãšã£ãŠã¯ããçš®ã®æœè±¡åã§ãããç¹å¥ãªãªããžããªããŒã¹ã¯ã©ã¹ã¯ååšããŸããã æåŸã«ãViewModelã¯ç¹å®ã®UIã«é©ãã圢åŒã§ããŸããŸãªãªããžããªãçµ±åããŸãã
ã¬ã€ã€ãŒéã®ããŒã¿ã¯ããµãã¹ã¯ãªãã·ã§ã³ãéããŠLiveDataã«éä¿¡ãããŸãã
äŸ
å°ããªãã¢ã¢ããªã±ãŒã·ã§ã³ãäœæããŸããã å€ãã®éœåžã®çŸåšã®å€©æ°ã衚瀺ããŸãã ç°¡åã«ããããã«ãéœåžã®ãªã¹ãã¯äºåå®çŸ©ãããŠããŸãã ããŒã¿ãããã€ããŒãšããŠã OpenWeatherMapãµãŒãã¹ã䜿çšãããŸãã
2ã€ã®ãã©ã°ã¡ã³ãããããŸããéœåžã®ãªã¹ãïŒCityListFragmentïŒãšéžæããéœåžã®å€©æ°ïŒCityFragmentïŒã§ãã äž¡æ¹ã®ãã©ã°ã¡ã³ãã¯MainActivityã«ãããŸãã
ã¢ã¯ãã£ããã£ãšãã©ã°ã¡ã³ãã¯åãMainActivityViewModelã䜿çšããŸãã
MainActivityViewModelã¯WeatherRepositoryã«ããŒã¿ãèŠæ±ããŠããŸãã
WeatherRepositoryã¯ããŒã¿ããŒã¹ããå€ãããŒã¿ãè¿ããããã«ãããã¯ãŒã¯çµç±ã§æŽæ°ãããããŒã¿ã®èŠæ±ãéå§ããŸãã æŽæ°ãããããŒã¿ãæ£åžžã«å°çãããšãããŒã¿ããŒã¹ã«ä¿åããããŠãŒã¶ãŒãç»é¢äžã§æŽæ°ããŸãã
æ£åžžã«åäœãããã«ã¯ãWeatherRepositoryã«APIããŒãç»é²ããå¿
èŠããããŸãã ããŒã¯ãOpenWeatherMapãžã®ç»é²åŸã«ç¡æã§ååŸã§ããŸãã
GitHubãªããžã㪠ã
驿°ã¯éåžžã«è峿·±ãããã«èŠããŸããããããç¶æãã䟡å€ãããéããã¹ãŠãããçŽãããšããè¡åã§ãã ããã¯ã¢ã«ãã¡ã®ã¿ã§ããããšãå¿ããªãã§ãã ããã
ã³ã¡ã³ããææ¡ãæè¿ããŸãã ãã£ãïŒ