离职在即,也没什么事情做,就鼓捣了一下。任意搭建了一个小框架,看看以后能不能搞出自己的一个model,好了。不说别的,上代码

1,先上依赖库

  1. compile 'io.reactivex:rxandroid:1.2.1'
  2. compile 'com.squareup.okhttp3:okhttp:3.3.1'
  3. compile 'io.reactivex:rxandroid:1.1.0'
  4. compile 'io.reactivex:rxjava:1.1.0'
  5. compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
  6. compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
  7. compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
  8. compile 'com.android.support:design:24.2.1'
  9. compile 'com.android.support:recyclerview-v7:24.2.1'
  10. compile 'com.android.support:cardview-v7:24.2.1'
  11. compile 'com.jakewharton:butterknife:7.0.1'
  12. compile 'com.github.bumptech.glide:glide:3.7.0'
  13. compile 'com.github.chrisbanes.photoview:library:1.2.3'

2。 依赖retrolambda

在app.build依赖

  1. apply plugin: 'me.tatarka.retrolambda'
  1. compileOptions {
  2. sourceCompatibility JavaVersion.VERSION_1_8
  3. targetCompatibility JavaVersion.VERSION_1_8
  4. }

然后在项目的app.build依赖

  1. classpath 'me.tatarka:gradle-retrolambda:3.2.5'

OK,到这里我们的环境搭建就完毕了

3。搭建Http请求模块

  1. 搭建工具类RetrofitUtils
    1. package mvpmaster.lht.com.lht.utils;
    2.  
    3. import com.squareup.okhttp.OkHttpClient;
    4.  
    5. import java.util.concurrent.TimeUnit;
    6.  
    7. import retrofit.GsonConverterFactory;
    8. import retrofit.Retrofit;
    9. import retrofit.RxJavaCallAdapterFactory;
    10.  
    11. /**
    12. * Created by Ly on 2016/10/14.
    13. */
    14.  
    15. public class RetrofitUtils {
    16. private static final int READ_TIMEOUT = 60;//读取超时时间 单位 秒
    17. private static final int CONN_TIMEOUT = 60;//连接超时时间 单位 秒
    18. private static Retrofit retrofit;
    19.  
    20. public RetrofitUtils() {
    21. }
    22.  
    23. public static Retrofit getInstance(String url) {
    24. retrofit = null;
    25. // 初始化一个okhttpClicent的对象 不然ref会自己加入一个
    26. OkHttpClient client = new OkHttpClient();
    27. // 设置读取时间为1分钟
    28. client.setReadTimeout(READ_TIMEOUT, TimeUnit.MINUTES);
    29. // 设置链接时间为12s
    30. client.setConnectTimeout(CONN_TIMEOUT, TimeUnit.SECONDS);
    31. retrofit = new Retrofit.Builder()
    32. .client(client)
    33. .baseUrl(url)
    34. .addConverterFactory(GsonConverterFactory.create())
    35. .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    36. .build();
    37. return retrofit;
    38. }
    39. }

    Ps,我发现这里并不能做到session的保持,在某些公司的后台并不能支持这种请求库,我稍候会上传一个更新后的版本号

  2. 这里写上我的一个interface(为什么我用了rx还要有callback???黑人问号脸)
    1. package mvpmaster.lht.com.lht.conf;
    2.  
    3. /**
    4. * Created by Ly on 2016/10/13.
    5. */
    6.  
    7. public interface OkHttpCallBack<T> {
    8. void onSuccess(T t);//成功的回调
    9.  
    10. void onFaild(Throwable e);//失败的回调
    11.  
    12. void onFinish();
    13. }
  3. 然后是一些比較通用的api文件了,我就不写凝视了
    1. package mvpmaster.lht.com.lht.conf;
    2.  
    3. /**
    4. * Created by Ly on 2016/11/2.
    5. */
    6.  
    7. public class HttpConf {
    8. private static final String ZHIHU_BASE_URL = "http://news-at.zhihu.com/api/4/";
    9. private static final String GANK_BASE_URL = "http://gank.io/api/";
    10. private static final String DAILY_BASE_URL = "http://app3.qdaily.com/app3/";
    11.  
    12. public static String getZhihuBaseUrl() {
    13. return ZHIHU_BASE_URL;
    14. }
    15.  
    16. public static String getGankBaseUrl() {
    17. return GANK_BASE_URL;
    18. }
    19.  
    20. public static String getDailyBaseUrl() {
    21. return DAILY_BASE_URL;
    22. }
    23. }
    1. package mvpmaster.lht.com.lht.conf;
    2.  
    3. /**
    4. * Created by Ly on 2016/11/2.
    5. */
    6.  
    7. public class HttpStatusConf {
    8. private static final int SUCCESS = 200;
    9.  
    10. public static int getSUCCESS() {
    11. return SUCCESS;
    12. }
    13. }
    1. package mvpmaster.lht.com.lht.utils;
    2.  
    3. import mvpmaster.lht.com.lht.ui.beanIml.DailyBean;
    4. import mvpmaster.lht.com.lht.ui.beanIml.NewsDetailBean;
    5. import mvpmaster.lht.com.lht.ui.beanIml.NewsTimeLine;
    6. import retrofit.http.GET;
    7. import retrofit.http.Path;
    8. import rx.Observable;
    9.  
    10. /**
    11. * Created by Ly on 2016/10/14.
    12. */
    13.  
    14. public interface APIService {
    15.  
    16. @GET("news/latest")
    17. Observable<NewsTimeLine> getZhiHuList();
    18.  
    19. @GET("news/before/{time}")
    20. Observable<NewsTimeLine> getBeforetNews(@Path("time") String time);
    21.  
    22. @GET("news/{id}")
    23. Observable<NewsDetailBean> getDetailNews(@Path("id") String id);
    24.  
    25. // for daily
    26. @GET("homes/index/{num}.json")
    27. Observable<DailyBean> getDailyTimeLine(@Path("num") String num);
    28.  
    29. }

4,网络请求搭建完了。重头戏来了,我们来搭建mvp的基本框架
  1. 我们的baseActivity
    1. package mvpmaster.lht.com.lht.base;
    2.  
    3. import android.content.Context;
    4. import android.os.Build;
    5. import android.os.Bundle;
    6. import android.support.annotation.Nullable;
    7. import android.support.design.widget.AppBarLayout;
    8. import android.support.v4.widget.SwipeRefreshLayout;
    9. import android.support.v7.app.ActionBar;
    10. import android.support.v7.app.AppCompatActivity;
    11. import android.support.v7.widget.Toolbar;
    12. import android.util.TypedValue;
    13. import android.view.MenuItem;
    14.  
    15. import butterknife.ButterKnife;
    16. import mvpmaster.lht.com.lht.R;
    17.  
    18. /**
    19. * Created by Ly on 2016/11/2.
    20. */
    21.  
    22. public abstract class BaseActivity<V, T extends BasePresenter<V>> extends AppCompatActivity {
    23.  
    24. protected T mPresenter;
    25. private AppBarLayout mAppBar;
    26. private Toolbar mToolbar;
    27. private SwipeRefreshLayout mRefreshLayout;
    28.  
    29. public Context mContext;
    30. private boolean mIsRequestDataRefresh = false;
    31.  
    32. @Override
    33. protected void onCreate(@Nullable Bundle savedInstanceState) {
    34. super.onCreate(savedInstanceState);
    35. mContext = this;
    36. // 同意为空 不是全部的都要实现这个模式
    37. if (createPresenter() != null) {
    38. mPresenter = createPresenter();
    39. mPresenter.attachView((V) this);
    40. }
    41. setContentView(provideContentViewId());
    42. ButterKnife.bind(this);
    43.  
    44. mAppBar = (AppBarLayout) findViewById(R.id.app_bar_layout);
    45. mToolbar = (Toolbar) findViewById(R.id.toolbar);
    46. if (mToolbar != null && mAppBar != null) {
    47. setSupportActionBar(mToolbar); //把Toolbar当做ActionBar给设置
    48.  
    49. if (canBack()) {
    50. ActionBar actionBar = getSupportActionBar();
    51. if (null != actionBar) {
    52. //设置ActionBar一个返回箭头。主界面没有,次级界面有
    53. actionBar.setDisplayHomeAsUpEnabled(true);
    54. }
    55. if (Build.VERSION.SDK_INT >= 21) {
    56. //Z轴浮动
    57. mAppBar.setElevation(10.6F);
    58. }
    59. }
    60. }
    61. if (isSetRefresh()) {
    62. setupSwipeRefresh();
    63. }
    64.  
    65. }
    66.  
    67. public static void toIntent(Context context, String... str) {
    68. }
    69.  
    70. @Override
    71. public boolean onOptionsItemSelected(MenuItem item) {
    72. // 此时android.R.id.home即为返回箭头
    73. if (item.getItemId() == android.R.id.home) {
    74. onBackPressed();
    75. finish();
    76. return true;
    77. } else {
    78. return super.onOptionsItemSelected(item);
    79. }
    80. }
    81.  
    82. @Override
    83. protected void onDestroy() {
    84. super.onDestroy();
    85. if (mPresenter != null) {
    86. mPresenter.detachView();
    87. }
    88. }
    89.  
    90. /**
    91. * 生成下拉刷新
    92. */
    93. private void setupSwipeRefresh() {
    94. mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
    95. if (null != mRefreshLayout) {
    96. mRefreshLayout.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimary);
    97. mRefreshLayout.setProgressViewOffset(true,
    98. 0,
    99. (int) TypedValue.applyDimension
    100. (TypedValue.COMPLEX_UNIT_DIP, 24, getResources()
    101. .getDisplayMetrics()));
    102. }
    103. }
    104.  
    105. /**
    106. * 设置刷新
    107. *
    108. * @param requestDataRefresh
    109. */
    110. public void setRefresh(boolean requestDataRefresh) {
    111. if (mRefreshLayout == null) {
    112. return;
    113. }
    114. if (!requestDataRefresh) {
    115. mIsRequestDataRefresh = false;
    116. mRefreshLayout.postDelayed(() -> {
    117. if (mRefreshLayout != null) {
    118. mRefreshLayout.setRefreshing(false);
    119. }
    120. }, 1000);
    121. } else {
    122. mRefreshLayout.setRefreshing(true);
    123. }
    124. }
    125.  
    126. /**
    127. * 数据刷新
    128. */
    129. public void requestDataRefresh() {
    130. mIsRequestDataRefresh = true;
    131. }
    132.  
    133. /**
    134. * 推断当前 Activity 是否同意返回
    135. * 主界面不同意返回,次级界面同意返回
    136. *
    137. * @return false
    138. */
    139. public boolean canBack() {
    140. return false;
    141. }
    142.  
    143. /**
    144. * 推断子Activity是否须要刷新功能
    145. *
    146. * @return false
    147. */
    148. public Boolean isSetRefresh() {
    149. return false;
    150. }
    151.  
    152. /**
    153. * 创建P
    154. *
    155. * @return T
    156. */
    157. protected abstract T createPresenter();
    158.  
    159. /**
    160. * 用于引入布局文件
    161. *
    162. * @return
    163. */
    164. abstract protected int provideContentViewId();
    165. }
    1. package mvpmaster.lht.com.lht.base;
    2.  
    3. import android.content.Context;
    4. import android.os.Bundle;
    5. import android.support.v4.app.Fragment;
    6. import android.support.v4.widget.SwipeRefreshLayout;
    7. import android.util.TypedValue;
    8. import android.view.LayoutInflater;
    9. import android.view.View;
    10. import android.view.ViewGroup;
    11.  
    12. import butterknife.ButterKnife;
    13. import mvpmaster.lht.com.lht.R;
    14.  
    15. /**
    16. * Created by Ly on 2016/11/2.
    17. */
    18.  
    19. public abstract class BaseFragment<V, T extends BasePresenter<V>> extends Fragment {
    20. protected Context mContext;
    21. protected T mPresenter;
    22.  
    23. private boolean mIsRequestDataRefresh = false;
    24. private SwipeRefreshLayout mRefreshLayout;
    25.  
    26. @Override
    27. public void onCreate(Bundle savedInstanceState) {
    28. super.onCreate(savedInstanceState);
    29. mContext = getActivity();
    30. mPresenter = createPresenter();
    31. mPresenter.attachView((V) this);
    32. }
    33.  
    34. @Override
    35. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    36. View rootView = inflater.inflate(createViewLayoutId(), container, false);
    37. ButterKnife.bind(this, rootView);
    38. initView(rootView);
    39. if (isSetRefresh()) {
    40. setupSwipeRefresh(rootView);
    41. }
    42. return rootView;
    43. }
    44.  
    45. @Override
    46. public void onDestroy() {
    47. super.onDestroy();
    48. mPresenter.detachView();
    49. }
    50.  
    51. private void setupSwipeRefresh(View view) {
    52. mRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refresh);
    53. if (mRefreshLayout != null) {
    54. mRefreshLayout.setColorSchemeResources(R.color.refresh_progress_1,
    55. R.color.refresh_progress_2, R.color.refresh_progress_3);
    56. mRefreshLayout.setProgressViewOffset(true, 0, (int) TypedValue
    57. .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources().getDisplayMetrics()));
    58. mRefreshLayout.setOnRefreshListener(this::requestDataRefresh);
    59. }
    60. }
    61.  
    62. public void requestDataRefresh() {
    63. mIsRequestDataRefresh = true;
    64. }
    65.  
    66. public void setRefresh(boolean requestDataRefresh) {
    67. if (mRefreshLayout == null) {
    68. return;
    69. }
    70. if (!requestDataRefresh) {
    71. mIsRequestDataRefresh = false;
    72. mRefreshLayout.postDelayed(() -> {
    73. if (mRefreshLayout != null) {
    74. mRefreshLayout.setRefreshing(false);
    75. }
    76. }, 1000);
    77. } else {
    78. mRefreshLayout.setRefreshing(true);
    79. }
    80. }
    81.  
    82. protected abstract T createPresenter();
    83.  
    84. protected abstract int createViewLayoutId();
    85.  
    86. protected void initView(View rootView) {
    87. }
    88.  
    89. public Boolean isSetRefresh() {
    90. return true;
    91. }
    92. }

    还有其它的一些base,我就不一一上传了。

  2. 说一下我理解的mvp。在我的看法中。mvp,m是要做一些耗时操作的,像读取网络数据,数据库数据。sp数据啊...这些脏活苦活所有都丢给它去做,我们在contract中给它定义好了interface,model类在自己本身去实现它。然后按着上层的要求去做那些苦活累活;而View呢?我认为通常是指我们的activity或者fragment巴,他们就负责一些比較轻松的东西了。像显示个toast啊,show一下dialog啊,拿一下editext的数据啊。最苦力也就是设置个适配器啊。监听一下滑动啊之类的,反正最轻松的那个就是它了;然后就是presenter了,这个类我认为挺难弄的,类似于红娘吧,它也要实现Contract的interface,并且要持有model和view的引用。在interface的回调里面去操控model类去做耗时操作,然后在对应的callback(怎么又是callback?)去操控view去实现各种交互。(不要喷我说得那么模糊,可是这样的东西写不出来,用了就会有这样的想法,并且。用了一次mvp,你就不会再想去用mvc了)
  3. 我们举一个样例,首页那里拿取了知乎的信息,用了一个recyclerview去显示拿到的数据。我们就用它来讲,我先上传一波项目文件夹,不然太懵逼了。
  4. 我们先看我们的fragment 
    1. package mvpmaster.lht.com.lht.ui.fragment.zhuhu;
    2.  
    3. import android.os.Bundle;
    4. import android.support.v7.widget.LinearLayoutManager;
    5. import android.support.v7.widget.RecyclerView;
    6. import android.view.View;
    7. import android.widget.Toast;
    8.  
    9. import butterknife.Bind;
    10. import mvpmaster.lht.com.lht.R;
    11. import mvpmaster.lht.com.lht.base.BaseFragment;
    12. import mvpmaster.lht.com.lht.ui.adapter.ZhiHuAdapter;
    13. import mvpmaster.lht.com.lht.ui.beanIml.NewsTimeLine;
    14.  
    15. /**
    16. * Created by Ly on 2016/11/2.
    17. */
    18.  
    19. public class ZhiHuFragment extends BaseFragment<ZhiHuContract.ZhiHuView, ZhiHuPresenter> implements ZhiHuContract.ZhiHuView {
    20. @Bind(R.id.content_list)
    21. RecyclerView mRlvZhiHu;
    22.  
    23. private LinearLayoutManager mLayoutManager;
    24. private ZhiHuAdapter zhiHuAdapter;
    25.  
    26. // 最后一个可见的视图
    27. private int lastVisibleItem;
    28. // 是否载入过很多其它
    29. private boolean isLoadMore = false;
    30. // 知乎日报须要的下一个參数
    31. private String time;
    32.  
    33. /**
    34. * 初始化配置
    35. */
    36. private void initConf() {
    37. // 适配器
    38. zhiHuAdapter = new ZhiHuAdapter(getActivity());
    39. // manager
    40. mLayoutManager = new LinearLayoutManager(getActivity());
    41. mRlvZhiHu.setLayoutManager(mLayoutManager);
    42. mRlvZhiHu.setAdapter(zhiHuAdapter);
    43. // 启动自己主动刷新配置
    44. setDataRefresh(true);
    45. // 获取第一次的数据
    46. mPresenter.getDataList();
    47. // 检測recView的滑动状态
    48. scrollRecycleView();
    49. }
    50.  
    51. /**
    52. * recyclerView Scroll listener , maybe in here is wrong ?
    53. */
    54. public void scrollRecycleView() {
    55. mRlvZhiHu.addOnScrollListener(new RecyclerView.OnScrollListener() {
    56. @Override
    57. public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
    58. super.onScrollStateChanged(recyclerView, newState);
    59. if (newState == RecyclerView.SCROLL_STATE_IDLE) {
    60. lastVisibleItem = mLayoutManager
    61. .findLastVisibleItemPosition();
    62. if (mLayoutManager.getItemCount() == 1) {
    63. zhiHuAdapter.updateLoadStatus(zhiHuAdapter.getLOAD_MORE());
    64. return;
    65. }
    66. if (lastVisibleItem + 1 == mLayoutManager
    67. .getItemCount()) {
    68. zhiHuAdapter.updateLoadStatus(zhiHuAdapter.getLOAD_PULL_TO());
    69. isLoadMore = true;
    70. zhiHuAdapter.updateLoadStatus(zhiHuAdapter.getLOAD_MORE());
    71. mPresenter.getBeforeDateList(time);
    72. }
    73. }
    74. }
    75.  
    76. @Override
    77. public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    78. super.onScrolled(recyclerView, dx, dy);
    79. lastVisibleItem = mLayoutManager.findLastVisibleItemPosition();
    80. }
    81. });
    82. }
    83.  
    84. @Override
    85. public void requestDataRefresh() {
    86. super.requestDataRefresh();
    87. setDataRefresh(true);
    88. mPresenter.getDataList();
    89. }
    90.  
    91. @Override
    92. protected ZhiHuPresenter createPresenter() {
    93. return new ZhiHuPresenter(this);
    94. }
    95.  
    96. @Override
    97. protected int createViewLayoutId() {
    98. return R.layout.fragment_zhihu;
    99. }
    100.  
    101. @Override
    102. public void setDataRefresh(boolean refresh) {
    103. setRefresh(refresh);
    104. }
    105.  
    106. public static ZhiHuFragment newInstance() {
    107. Bundle args = new Bundle();
    108. ZhiHuFragment fragment = new ZhiHuFragment();
    109. fragment.setArguments(args);
    110. return fragment;
    111. }
    112.  
    113. @Override
    114. public void loadFinishAndReset(NewsTimeLine newsTimeLine, String time) {
    115. zhiHuAdapter.resetData(newsTimeLine);
    116. setDataRefresh(false);
    117. this.time = time;
    118. }
    119.  
    120. @Override
    121. public void loadFinishAndAdd(NewsTimeLine newsTimeLine, String time) {
    122. zhiHuAdapter.addData(newsTimeLine);
    123. this.time = time;
    124. }
    125.  
    126. @Override
    127. public void loadFailure() {
    128. setDataRefresh(false);
    129. zhiHuAdapter.updateLoadStatus(zhiHuAdapter.getLOAD_FAILURE());
    130. }
    131.  
    132. @Override
    133. protected void initView(View rootView) {
    134. super.initView(rootView);
    135. initConf();
    136. }
    137.  
    138. @Override
    139. public void TsShow(String msg) {
    140. Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show();
    141. }
    142. }

    我们在这个看到一个mPresenter。这个是什么鬼?是从哪里来的?事实上这个就是Presenter的对象了。也是BaseActivity的泛型里面的那个

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">我们点取查看它的引用,发如今这个fragment里面一共被引用了3次。第一次是刚进去页面的时候,第一次读取数据。第二个是下拉载入的时候,读取了下一波的数据。再有一次是上拉刷新的时候。我们又一次刷新了一次页面拿取了最新的一波数据,可是?拿数据的在哪里呢?网络请求呢?在哪里??

  5. 我们看Presenter里面做的操作吧:
    1. package mvpmaster.lht.com.lht.ui.fragment.zhuhu;
    2.  
    3. import mvpmaster.lht.com.lht.base.BasePresenter;
    4. import mvpmaster.lht.com.lht.conf.OkHttpCallBack;
    5. import mvpmaster.lht.com.lht.ui.beanIml.NewsTimeLine;
    6.  
    7. /**
    8. * Created by Ly on 2016/11/2.
    9. */
    10.  
    11. public class ZhiHuPresenter extends BasePresenter<ZhiHuContract.ZhiHuView> implements ZhiHuContract.ZhiHuPresenter {
    12. private ZhiHuContract.ZhiHuView zhiHuView;
    13. private ZhiHuContract.ZhiHuModel zhiHuModel;
    14.  
    15. public ZhiHuPresenter(ZhiHuContract.ZhiHuView zhiHuView) {
    16. this.zhiHuView = zhiHuView;
    17. zhiHuModel = new ZhiHuModel();
    18. }
    19.  
    20. @Override
    21. public void getDataList() {
    22. zhiHuModel.getDataList(new OkHttpCallBack<NewsTimeLine>() {
    23. @Override
    24. public void onSuccess(NewsTimeLine newsTimeLine) {
    25. zhiHuView.loadFinishAndReset(newsTimeLine, newsTimeLine.getDate());
    26. }
    27.  
    28. @Override
    29. public void onFaild(Throwable e) {
    30. loadError(e);
    31. zhiHuView.loadFailure();
    32. }
    33.  
    34. @Override
    35. public void onFinish() {
    36.  
    37. }
    38. });
    39. }
    40.  
    41. @Override
    42. public void getBeforeDateList(String time) {
    43. zhiHuModel.getBeforeDateList(time, new OkHttpCallBack<NewsTimeLine>() {
    44. @Override
    45. public void onSuccess(NewsTimeLine newsTimeLine) {
    46. zhiHuView.loadFinishAndAdd(newsTimeLine, newsTimeLine.getDate());
    47. }
    48.  
    49. @Override
    50. public void onFaild(Throwable e) {
    51. loadError(e);
    52. zhiHuView.loadFailure();
    53. }
    54.  
    55. @Override
    56. public void onFinish() {
    57.  
    58. }
    59. });
    60. }
    61.  
    62. private void loadError(Throwable throwable) {
    63. throwable.printStackTrace();
    64. zhiHuView.TsShow(throwable.getMessage());
    65. }
    66. }

    我们看到有三个ovver的方法。各自是刷新(第一次读取),载入。读取失败 三种情况:我们能够看到,这个类持有了View和Model两个模块,在方法体里面,我们调用了model的方法去做耗时,在结果方法体里面我们调用了view的方法去改动UI,同一时候presenter这个模块又被view持有了,view能够在声明周期里面去调用特定的方法,view和presenter相互沟通。view和model全然隔离,presenter调控model,presenter沟通全局。

补上我的git地址:https://github.com/LinHuanTanLy/mvpMaster
补上另外一个请求框架:https://github.com/LinHuanTanLy/OkHttpWithSession

一个小框架,基于rx_retrofit2_mvp的更多相关文章

  1. 利用jdbc简单封装一个小框架(类似DBUtils)

    利用jdbc写的一个类似DBUtils的框架 package com.jdbc.orm.dbutils; import java.io.IOException; import java.io.Inpu ...

  2. mpvue最佳实践 , 美团出的一个小程序框架

    看手机微信,看到说美团出了1个小程序框架,  mpvue 搜下来试试,看了网上的一个对比 ----------------- 以下为引用 我们对微信小程序.mpvue.WePY 这三个开发框架的主要能 ...

  3. 通过Dapr实现一个简单的基于.net的微服务电商系统(十四)——开发环境容器调试小技巧

    之前有很多同学提到如何做容器调试,特别是k8s环境下的容器调试,今天就讲讲我是如何调试的.大家都知道在vs自带的创建项目模板里勾选docker即可通过F5启动docker容器调试.但是对于启动在k8s ...

  4. 通过Dapr实现一个简单的基于.net的微服务电商系统(二十)——Saga框架实现思路分享

    今天这篇博文的主要目的是分享一下我设计Saga的实现思路来抛砖引玉,其实Saga本身非常的类似于一个简单的工作流体系,相比工作流不一样的部分在于它没有工作流的复杂逻辑处理机制(比如会签),没有条件分支 ...

  5. 分析一个类似于jquery的小框架

    在网上下了一个类似于jQuery的小框架,分析源码,看看怎么写框架. 选择器Select //用沙箱闭包其整个代码,只有itcast和I暴漏在全局作用域 (function( window , und ...

  6. 一个可以代替冗长switch-case的消息分发小框架

    在项目中,我需要维护一个应用层的字节流协议.这个协议的每条报文都是一个字节数组,数组的头两个字节表示消息的传送方向,第三.四个字节表示消息ID,也就是消息种类,再往后是消息内容.时间戳.校验码等……整 ...

  7. 2、基于wsgiref模块DIY一个web框架

    一 web框架 Web框架(Web framework)是一种开发框架,用来支持动态网站.网络应用和网络服务的开发.这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方 ...

  8. spring security 一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中 配置的Bean,充分利用了Spring ...

  9. 任务驱动,对比式学习.NET开发系列之开篇------开源2个小框架(一个Winform框架,一个Web框架)

    一 源码位置 1. Winform框架 2. web框架 二 高效学习编程的办法 1 任务驱动方式学习软件开发 大部分人学习软件开发技术是通过看书,看视频,听老师上课的方式.这些方式有一个共同点即按知 ...

随机推荐

  1. DTrace Probes in HotSpot VM

    http://docs.oracle.com/javase/6/docs/technotes/guides/vm/dtrace.html

  2. 报错:System.NotSupportedException: LINQ to Entities does not recognize the method

    报错:System.NotSupportedException: LINQ to Entities does not recognize the method ...... get_Item(Int3 ...

  3. 内存溢出导致jenkins自动部署到tomcat失败

    原文地址:http://openwares.net/java/jenkens_deploy_to_tomcat_error_of_outofmemoryerror.html jenkins自动部署wa ...

  4. PostgreSQL学习手册(目录)

    原文地址:http://www.cnblogs.com/stephen-liu74/archive/2012/06/08/2315679.html 事实上之前有很长一段时间都在纠结是否有必要好好学习它 ...

  5. JMeter学习(二十三)关联

    话说LoadRunner有的一些功能,比如:参数化.检查点.集合点.关联,Jmeter也都有这些功能,只是功能可能稍弱一些,今天就关联来讲解一下. JMeter的关联方法有两种:后置处理器-正则表达式 ...

  6. python测试开发django-22.admin首页和title修改

    前言 django的admin首页默认显示的"Django 管理",title显示的是"Django 站点管理员",这里的文案内容可以修改成自己项目的后台页面内 ...

  7. Unity中的内存泄漏

    在对内存泄漏有一个基本印象之后,我们再来看一下在特定环境——Unity下的内存泄漏.大家都知道,游戏程序由代码和资源两部分组成,Unity下的内存泄漏也主要分为代码侧的泄漏和资源侧的泄漏,当然,资源侧 ...

  8. spring4 quartz2 集群动态任务

    实现定时任务的执行,而且要求定时周期是不固定的.测试地址:http://sms.reyo.cn 生产环境:nginx+tomcat+quartz2.2.1+spring4.2.1 集群. 实现功能:可 ...

  9. ios之gcd浅析

    A.普通的GCD异步运行与主线程更新写法: dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^ ...

  10. ios之网络异常与正常视图的切换

    1. xib中创建两个View 2. View的视图大概如下第一个:View View 第二个:View 3. 代码切换: [self.view addSubview:_redView];  // 会 ...