標籤:
Presention層: 整個應用啟動的時候,就執行依賴的初始化。編譯項目之後,Dagger依賴架構使用ApplicationComponent產生一個DaggerApplicationCOmponent。
1. 首先進行依賴的產生在Application中,調用initializeInjector()就會促使Dagger架構進行依賴產生。
ApplicationComponent對其它Component提供Context,ThreadExecutor,PostExecutionThread,UserRepository依賴
/**
* A component whose lifetime is the life of the application.
*/
@Singleton // Constraints this component to one-per-application or unscoped bindings.
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(BaseActivity baseActivity);
//Exposed to sub-graphs.
Context context();
ThreadExecutor threadExecutor();
PostExecutionThread postExecutionThread();
UserRepository userRepository();
}
ApplicationModule
/**
* Dagger module that provides objects which will live during the application lifecycle.
*/
@Module
public class ApplicationModule {
private final AndroidApplication application;
public ApplicationModule(AndroidApplication application) {
this.application = application;
}
@Provides @Singleton Context provideApplicationContext() {
return this.application;
}
@Provides @Singleton Navigator provideNavigator() {
return new Navigator();
}
@Provides @Singleton ThreadExecutor provideThreadExecutor(JobExecutor jobExecutor) {
return jobExecutor;
}
@Provides @Singleton PostExecutionThread providePostExecutionThread(UIThread uiThread) {
return uiThread;
}
@Provides @Singleton UserCache provideUserCache(UserCacheImpl userCache) {
return userCache;
}
@Provides @Singleton UserRepository provideUserRepository(UserDataRepository userDataRepository) {
return userDataRepository;
}
}
在這個類中,提供了產生依賴的方法。需要參數的provide方法,參數也是通過Dagger依賴架構產生的。參數JobExecutor(data模組),UIThread(presentation模組),UserCacheImpl(data模組),UserDataRepository(data模組)產生的方式,是Dagger依賴架構調用相應類的構造方法實現的,而不是通過provide實現的。比如JobExecutor(data模組):public class JobExecutor implements ThreadExecutor { @Inject public JobExecutor() { this.workQueue = new LinkedBlockingQueue<>(); this.threadFactory = new JobThreadFactory(); this.threadPoolExecutor = new ThreadPoolExecutor(INITIAL_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT, this.workQueue, this.threadFactory); }...}屬於data模組的:參數JobExecutor(data模組),UserCacheImpl(data模組),UserDataRepository(data模組)
Application:
/**
* Android Main Application
*/
public class AndroidApplication extends Application {
private ApplicationComponent applicationComponent;
@Override public void onCreate() {
super.onCreate();
this.initializeInjector();
}
private void initializeInjector() {
this.applicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
}
public ApplicationComponent getApplicationComponent() {
return this.applicationComponent;
}
}
2.MainActivity實現 使用ButterKnife對View對象進行注入,從而無需寫findViewById。
2.1繼承BaseActivity,BaseActivity的實現 A.聲明了一個帶有Inject註解的成員Navigator在onCreate方法中,將Navigator依賴注入到當前執行個體。 B.提供三個protected方法,一個是用來添加fragment到當前介面的某個位置;兩個是用來進行依賴注入的。
2.2 MainActivity執行流程使用者點擊R.id.btn_LoadData Button,就會跳轉到介面
UserListActivity.
3.UserListActivity實現 A.介面載入,使用UserListFragment。 B.在onCreate方法中,執行UserComponent包含的依賴初始化。 private void initializeInjector() { this.userComponent = DaggerUserComponent.builder() .applicationComponent(getApplicationComponent()) .activityModule(getActivityModule()) .build(); } UserComponent產生的依賴,被注入到UserListFragment,UserDetailsFragment。UserListFragment,UserDetailsFragment調用UserComponent執行個體的inject方法。
UserComponent如下:
可以注入到UserListFragment,UserDetailsFragment的依賴是GetUserListUseCase,GetUserDetailsUseCase。
,
/**
* A scope {@link com.fernandocejas.android10.sample.presentation.internal.di.PerActivity} component.
* Injects user specific Fragments.
*/
@PerActivity
@Component(dependencies = ApplicationComponent.class, modules = {ActivityModule.class, UserModule.class})
public interface UserComponent extends ActivityComponent {
void inject(UserListFragment userListFragment);
void inject(UserDetailsFragment userDetailsFragment);
}
/**
* A base component upon which fragment‘s components may depend.
* Activity-level components should extend this component.
*
* Subtypes of ActivityComponent should be decorated with annotation:
* {@link com.fernandocejas.android10.sample.presentation.internal.di.PerActivity}
*/
@PerActivity
@Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
//Exposed to sub-graphs.
Activity activity();
}
/**
* A module to wrap the Activity state and expose it to the graph.
*/
@Module
public class ActivityModule {
private final Activity activity;
public ActivityModule(Activity activity) {
this.activity = activity;
}
/**
* Expose the activity to dependents in the graph.
*/
@Provides @PerActivity Activity activity() {
return this.activity;
}
}
/**
* Dagger module that provides user related collaborators.
*/
@Module
public class UserModule {
private int userId = -1;
public UserModule() {}
public UserModule(int userId) {
this.userId = userId;
}
@Provides @PerActivity @Named("userList") UseCase provideGetUserListUseCase(
GetUserListUseCase getUserListUseCase) {
return getUserListUseCase;
}
@Provides @PerActivity @Named("userDetails") UseCase provideGetUserDetailsUseCase(
UserRepository userRepository, ThreadExecutor threadExecutor,
PostExecutionThread postExecutionThread) {
return new GetUserDetailsUseCase(userId, userRepository, threadExecutor, postExecutionThread);
}
}
4.UserListFragment的實現 A.UserListFragment實現UserListView介面,用來表示View層。B.UserListFragment跟宿主Activity的通訊,通過UserListFragment聲明的介面UserListListener來實現。
@Override public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof UserListListener) {
this.userListListener = (UserListListener) activity;
}
} C.當宿主Activity建立成功之後,回調方法:
@Override public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
this.initialize();
this.loadUserList();
}在UserListFragment類中,使用Inject註解,聲明了一個成員@Inject UserListPresenter userListPresenter;然後,調用UserComponent執行個體的方法inject,就可以將依賴userListPresenter注入到UserListFragment執行個體中。調用userListPresenter的方法setView,建立Presenter和View之間的關係。
private void initialize() {
this.getComponent(UserComponent.class).inject(this);
this.userListPresenter.setView(this);
}調用loadUserList方法,會載入所有使用者資料。
/**
* Loads all users.
*/
private void loadUserList() {
this.userListPresenter.initialize();
}
介面的資料載入操作,都被封裝在userListPresenter的initalize方法中。展示介面載入效果;執行擷取資料操作;資料載入成功之後,顯示對應的介面。這些都由userListPresenter來實現和控制。
5.UserListPresenter A.調用構造方法,構造方法的參數,由Dagger注入。
@Inject
public UserListPresenter(@Named("userList") UseCase getUserListUserCase, UserModelDataMapper userModelDataMapper) {
this.getUserListUseCase = getUserListUserCase;
this.userModelDataMapper = userModelDataMapper;
}
B.提供initialize方法,供其它類調用。調用該方法,展示介面載入效果;擷取所有使用者資料。
/**
* Initializes the presenter by start retrieving the user list.
*/
public void initialize() {
this.loadUserList();
}
/**
* Loads all users.
*/
private void loadUserList() {
this.hideViewRetry();
this.showViewLoading();
this.getUserList();
}
private void getUserList() {
this.getUserListUseCase.execute(this); //這裡使用到了domain層上的類,domain層提供用例類。一個用例類表示一個表示一個業務,在這裡表示擷取使用者列表。
}
6.UserListPresenter和UseCase的協作 UserListPresenter和UseCase的協作,使用 The RxJava Android Module 架構 1.UserListPresenter屬於Presention層,它依賴domain層和data層。 2.UseCase是domain層,它的執行個體是GetUserListUseCase,這個是由Presention層中的依賴定義包指定的,如下:com.fernandocejas.android10.sample.presentation.internal.di.modules.UserModule: @Provides @PerActivity @Named("userList") UseCase provideGetUserListUseCase( GetUserListUseCase getUserListUseCase) { return getUserListUseCase; } -----所以,GetUserListUseCase是必須是可注入的,要在其建構函式中添加@Inject註解。 3.UserListPresenter和GetUserListUseCase,UserListPresenter是一個訂閱者;這個訂閱者訂閱的流是CloudUserDataStore執行個體的方法getUseEntityList()產出來之後,經過映射的流,該流是長這個樣子的: @Override public Observable<List<User>> getUsers() { //we always get all users from the cloud final UserDataStore userDataStore = this.userDataStoreFactory.createCloudDataStore(); return userDataStore.getUserEntityList().map(userListEntityMapper); } 總結牽涉到的類及所在的層:
presentation層:UserListPresenter。
domain層: GetUseerListUseCase,UseCase
data層:UserDataRepository,CloudUserDataStore,UserDataStoreFactory presentation層依賴domain層和data層。
7.整個項目使用到的架構技術 1.Dagger依賴產生,定義依賴的建置規則。2.RxAndroid 響應式編程範式的應用,用事件流的方式來處理非同步事件。3.okHttp,網路請求應用到該架構。
8.整個項目閱讀下來,可以學習到的東西 1.使用依賴注入,一個執行個體包含其它執行個體,在擷取其它執行個體的使用,使用依賴注入,不將其它執行個體的產生方式暴露出去。這樣,使用者只關注使用,無需關注怎樣執行個體化,其它執行個體執行個體化的過程對使用者隱藏掉。 2.分層,分模組,這個要針對功能的含義來劃分,根據關注點來劃分。presentation層,我們只關注介面展示,我們在這一層裡面,我們只需要關注介面展示方面的代碼,我們只放介面展示代碼在這一層上,還有依賴產生的程式碼。在這層,我們重點只關注介面代碼,還有依賴產生的規則。 domain層,領域層,用例層,從這個模組中包的命名就可以知道,它表示抽象程度高的業務,與系統平台無關的業務。在這個應用中,有兩個業務,一個是擷取使用者列表,一個是擷取使用者的詳細資料。在這一層,存放業務的實現代碼。data層,資料擷取,資料存放區的實現代碼放在這一層。
層之間的依賴規則:presention層------>domain層-------擷取資料---->data層
參考資料:http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/
例子Architecting Android…The clean way?----程式碼分析