工程树:
TaskDetail
- TaskDetailActivity [ V ]
- TaskDetailFragment [ V ]
- TaskDetailContract [ M < - P - >V ]
- TaskDetailPresenter [ P ]
- TaskDetailPresenterModule [ Module ]
- TaskDetailComponent [ Component ]
- App
- AppModule
Data
- Local 本地数据
- Remote 网络数据
- TasksDataSource 数据逻辑
- TasksRepository 数据处理
- TasksRepositoryModule [ Module ]
- TasksRepositoryComponent [ Component ]
TaskDetailActivity TaskDetailFragment
主要工作:
1. 编辑Toolbar
2. 加载Fragment
3. 实例化Presenter
编辑Toolbar
// Set up the toolbar.
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowHomeEnabled(true);
加载Fragment
TaskDetailFragment mTaskDetailFragment = (TaskDetailFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
if (mTaskDetailFragment == null) {
mTaskDetailFragment = TaskDetailFragment.newInstance();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.contentFrame, mTaskDetailFragment);
transaction.commit();
}
实例化Presenter
1. 建立一个依赖提供类 TaskDetailPresenterModule
@Module
public class TaskDetailPresenterModule {
private TaskDetailContract.View mView;
public TaskDetailPresenterModule(TaskDetailContract.View mView) {
this.mView = mView;
}
@Provides
TaskDetailContract.View provideView() {
return mView;
}
在MVP模式中,所依赖的是的是View,所以 provideView() 作为专门提供依赖的方法
2. 在TaskDetailPresenter中进行注入,因为Presenter是主持人,由它调用view的方法
public class TaskDetailPresenter implements TaskDetailContract.Presenter {
TaskDetailContract.View mView;
@Inject
public TaskDetailPresenter(TaskDetailContract.View mView) {
this.mView = mView;
}
}
3. 连接Inject和Moudle,构建注射器Comonpent
@Component(modules = TaskDetailPresenterModule.class)
public interface TaskDetailComponent {
void inject(TaskDetailActivity mTaskDetailActivity);
}
4. 注入,产生Presenter实例
@Inject
TaskDetailPresenter mTaskDetailPresenter;
DaggerTaskDetailComponent.builder()
.taskDetailPresenterModule(new TaskDetailPresenterModule(mTaskDetailFragment))
.build().inject(this);
5. 虽然已经产生了TaskDetailPresenter,但是 V - P 还没联系起来,下面开始搭建 V - P 的关系。
TaskDetailContract
1. 建立联系人
public class TaskDetailContract {
interface View {
void setPresenter(Presenter mPresenter);
}
interface Presenter {
}
}
2. 实现接口,关联 V - P
public class TaskDetailFragment extends Fragment implements TaskDetailContract.View{
private TaskDetailContract.Presenter mPresenter;
@Override
public void setPresenter(TaskDetailContract.Presenter mPresenter) {
this.mPresenter = mPresenter;
}
}
3. 用@Inject注解injectPresenter()方法,生成的代码中会调用该方法,,该方法在TaskDetailFragment中实现,这样把 P -> V 联系起来了
public class TaskDetailPresenter implements TaskDetailContract.Presenter {
TaskDetailContract.View mView;
@Inject
public TaskDetailPresenter(TaskDetailContract.View mView) {
this.mView = mView;
}
@Inject
void injectPresenter() {
mView.setPresenter(this);
}
}
TaskDetailComponent
最后一步就是建立注射器,把inject和moudle开动起来。
@Component(modules = TaskDetailPresenterModule.class)
public interface TaskDetailComponent {
void inject(TaskDetailActivity mTaskDetailActivity);
}
在Acticitu中,进行调用,其中taskDetailPresenterModule是带参数的
DaggerTaskDetailComponent.builder()
.taskDetailPresenterModule(new TaskDetailPresenterModule(mTaskDetailFragment))
.build().inject(this);
Data
数据源分为 本地 和 网络
TasksLocalDataSource
@Singleton
public class TasksLocalDataSource implements TasksDataSource {
private Context mContext;
@Inject
public TasksLocalDataSource(Context mContext) {
this.mContext = mContext;
}
}
@Singleton表示单例模式,因为我们始终操作的都是同一个数据源对象
而context常常被本地数据用到,所以建立一个依赖
context由AppMoudle提供
@Module
public class AppModule {
private final Context mContext;
public AppModule(Context mContext) {
this.mContext = mContext;
}
@Provides
Context provideContext() {
return mContext;
}
}
TasksRemoteDataSource
@Singleton
public class TasksRemoteDataSource implements TasksDataSource {
@Inject
public TasksRemoteDataSource() {
}
}
TasksDataSource
无论本地还是网络数据的行为,统一实现TasksDataSource接口
public interface TasksDataSource {
}
Local && Remote
当依赖为可选多个的时候,适用@Qualifier命名各自的作用域
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Local {
}
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Remote {
}
TasksDataRepository
在TasksDataRepository中,实现TasksDataSource的方法
@Singleton
public class TasksDataRepository implements TasksDataSource{
private final TasksDataSource mTasksRemoteDataSource;
private final TasksDataSource mTasksLocalDataSource;
@Inject
public TasksDataRepository(@Remote TasksDataSource mTasksRemoteDataSource, @Local TasksDataSource mTasksLocalDataSource) {
this.mTasksRemoteDataSource = mTasksRemoteDataSource;
this.mTasksLocalDataSource = mTasksLocalDataSource;
}
}
TasksRepositoryModule
提供数据依赖,由于TasksDataSource由TasksLocalDataSource和TasksRemoteDataSource络产生,所以
@Module
public class TasksRepositoryModule {
@LocalScoped
@Singleton
@Provides
TasksDataSource provideLocalData(Context mContext) {
return new TasksLocalDataSource(mContext);
}
@RemoteScoped
@Singleton
@Provides
TasksDataSource provideRemoteData() {
return new TasksRemoteDataSource();
}
}
TasksRepositoryComponent
构建注射器
@Singleton
@Component(modules = {TasksRepositoryModule.class, AppModule.class})
public interface TasksRepositoryComponent {
TasksDataRepository getTasksDataRepository();
}
这样一个TasksRepositoryComponent就准备好了
最后一步:注入
我们选择在App主要类中进行构建
public class App extends Application {
private TasksRepositoryComponent mTasksRepositoryComponent;
@Override
public void onCreate() {
super.onCreate();
mTasksRepositoryComponent = DaggerTasksRepositoryComponent.builder()
.appModule(new AppModule(getApplicationContext()))
.build();
}
public TasksRepositoryComponent getTasksRepositoryComponent() {
return mTasksRepositoryComponent;
}
}
这样就可以到一个TasksRepositoryComponent实例
至此,我们MVP中的M就构建好了
TaskDetailActivity
M-V-P都已经准备完毕,之后就把三者联系起来
public class TaskDetailActivity extends AppCompatActivity {
@Inject
TaskDetailPresenter mTaskDetailPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_task_detail);
. . .
DaggerTaskDetailComponent.builder()
.taskDetailPresenterModule(new TaskDetailPresenterModule(mTaskDetailFragment))
.tasksRepositoryComponent(((App) getApplication()).getTasksRepositoryComponent())
.build().inject(this);
}
}
App
public class App extends Application {
private DataComponent mDataComponent;
@Override
public void onCreate() {
super.onCreate();
mDataComponent = DaggerDataComponent.builder()
.appModule(new AppModule(getApplicationContext()))
.build();
}
public DataComponent getDataComponent() {
return mDataComponent;
}
}
AppModule
@Module
public class AppModule {
private final Context mContext;
public AppModule(Context mContext) {
this.mContext = mContext;
}
@Provides
public Context provideContext() {
return mContext;
}
}
RxJava
主要用在数据请求上
在TasksDataSource中,定义一个观察者
Observable<Task> getTask(@NonNull String taskId);
在TasksRepository中,实现逻辑
Observable<Task> getTask(@NonNull String taskId) {
return mTasksLocalDataSource.getTask(taskId);
}
在TasksLocalDataSource创建观察者
@Override
public Observable<Task> getTask(@NonNull String taskId) {
String[] projection = {
TaskEntry.COLUMN_NAME_ENTRY_ID,
TaskEntry.COLUMN_NAME_TITLE,
TaskEntry.COLUMN_NAME_DESCRIPTION,
TaskEntry.COLUMN_NAME_COMPLETED
};
String sql = String.format("SELECT %s FROM %s WHERE %s LIKE ?",
TextUtils.join(",", projection), TaskEntry.TABLE_NAME, TaskEntry.COLUMN_NAME_ENTRY_ID);
return mDatabaseHelper.createQuery(TaskEntry.TABLE_NAME, sql, taskId)
.mapToOneOrDefault(mTaskMapperFunction, null);
}
在TaskDetailContract中创建订阅和取消订阅
public class TaskDetailContract {
interface View {
void setPresenter(Presenter mPresenter);
}
interface Presenter {
void subscribe();
void unsubscribe();
}
}
在View中调用方法
@Override
public void onResume() {
super.onResume();
mPresenter.subscribe();
}
@Override
public void onPause() {
super.onPause();
mPresenter.unsubscribe();
}
在TaskDetailPresenter中实现
@Override
public void subscribe() {
}
@Override
public void unsubscribe() {
mCompositeDisposable.clear();
}
值得一提的是,在RxJava中,对于订阅者的管理,我们需要用到CompositeDisposable
CompositeDisposable mCompositeDisposable= new CompositeDisposable();
mCompositeDisposable.add(mSubscribe);