一个小框架,基于rx_retrofit2_mvp
离职在即,也没什么事情做,就鼓捣了一下。任意搭建了一个小框架,看看以后能不能搞出自己的一个model,好了。不说别的,上代码
1,先上依赖库
- compile 'io.reactivex:rxandroid:1.2.1'
- compile 'com.squareup.okhttp3:okhttp:3.3.1'
- compile 'io.reactivex:rxandroid:1.1.0'
- compile 'io.reactivex:rxjava:1.1.0'
- compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
- compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
- compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
- compile 'com.android.support:design:24.2.1'
- compile 'com.android.support:recyclerview-v7:24.2.1'
- compile 'com.android.support:cardview-v7:24.2.1'
- compile 'com.jakewharton:butterknife:7.0.1'
- compile 'com.github.bumptech.glide:glide:3.7.0'
- compile 'com.github.chrisbanes.photoview:library:1.2.3'
2。 依赖retrolambda
在app.build依赖
- apply plugin: 'me.tatarka.retrolambda'
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
然后在项目的app.build依赖
- classpath 'me.tatarka:gradle-retrolambda:3.2.5'
OK,到这里我们的环境搭建就完毕了
3。搭建Http请求模块
- 搭建工具类RetrofitUtils
- package mvpmaster.lht.com.lht.utils;
- import com.squareup.okhttp.OkHttpClient;
- import java.util.concurrent.TimeUnit;
- import retrofit.GsonConverterFactory;
- import retrofit.Retrofit;
- import retrofit.RxJavaCallAdapterFactory;
- /**
- * Created by Ly on 2016/10/14.
- */
- public class RetrofitUtils {
- private static final int READ_TIMEOUT = 60;//读取超时时间 单位 秒
- private static final int CONN_TIMEOUT = 60;//连接超时时间 单位 秒
- private static Retrofit retrofit;
- public RetrofitUtils() {
- }
- public static Retrofit getInstance(String url) {
- retrofit = null;
- // 初始化一个okhttpClicent的对象 不然ref会自己加入一个
- OkHttpClient client = new OkHttpClient();
- // 设置读取时间为1分钟
- client.setReadTimeout(READ_TIMEOUT, TimeUnit.MINUTES);
- // 设置链接时间为12s
- client.setConnectTimeout(CONN_TIMEOUT, TimeUnit.SECONDS);
- retrofit = new Retrofit.Builder()
- .client(client)
- .baseUrl(url)
- .addConverterFactory(GsonConverterFactory.create())
- .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
- .build();
- return retrofit;
- }
- }
Ps,我发现这里并不能做到session的保持,在某些公司的后台并不能支持这种请求库,我稍候会上传一个更新后的版本号
- 这里写上我的一个interface(为什么我用了rx还要有callback???黑人问号脸)
- package mvpmaster.lht.com.lht.conf;
- /**
- * Created by Ly on 2016/10/13.
- */
- public interface OkHttpCallBack<T> {
- void onSuccess(T t);//成功的回调
- void onFaild(Throwable e);//失败的回调
- void onFinish();
- }
- 然后是一些比較通用的api文件了,我就不写凝视了
- package mvpmaster.lht.com.lht.conf;
- /**
- * Created by Ly on 2016/11/2.
- */
- public class HttpConf {
- private static final String ZHIHU_BASE_URL = "http://news-at.zhihu.com/api/4/";
- private static final String GANK_BASE_URL = "http://gank.io/api/";
- private static final String DAILY_BASE_URL = "http://app3.qdaily.com/app3/";
- public static String getZhihuBaseUrl() {
- return ZHIHU_BASE_URL;
- }
- public static String getGankBaseUrl() {
- return GANK_BASE_URL;
- }
- public static String getDailyBaseUrl() {
- return DAILY_BASE_URL;
- }
- }
- package mvpmaster.lht.com.lht.conf;
- /**
- * Created by Ly on 2016/11/2.
- */
- public class HttpStatusConf {
- private static final int SUCCESS = 200;
- public static int getSUCCESS() {
- return SUCCESS;
- }
- }
- package mvpmaster.lht.com.lht.utils;
- import mvpmaster.lht.com.lht.ui.beanIml.DailyBean;
- import mvpmaster.lht.com.lht.ui.beanIml.NewsDetailBean;
- import mvpmaster.lht.com.lht.ui.beanIml.NewsTimeLine;
- import retrofit.http.GET;
- import retrofit.http.Path;
- import rx.Observable;
- /**
- * Created by Ly on 2016/10/14.
- */
- public interface APIService {
- @GET("news/latest")
- Observable<NewsTimeLine> getZhiHuList();
- @GET("news/before/{time}")
- Observable<NewsTimeLine> getBeforetNews(@Path("time") String time);
- @GET("news/{id}")
- Observable<NewsDetailBean> getDetailNews(@Path("id") String id);
- // for daily
- @GET("homes/index/{num}.json")
- Observable<DailyBean> getDailyTimeLine(@Path("num") String num);
- }
- 我们的baseActivity
- package mvpmaster.lht.com.lht.base;
- import android.content.Context;
- import android.os.Build;
- import android.os.Bundle;
- import android.support.annotation.Nullable;
- import android.support.design.widget.AppBarLayout;
- import android.support.v4.widget.SwipeRefreshLayout;
- import android.support.v7.app.ActionBar;
- import android.support.v7.app.AppCompatActivity;
- import android.support.v7.widget.Toolbar;
- import android.util.TypedValue;
- import android.view.MenuItem;
- import butterknife.ButterKnife;
- import mvpmaster.lht.com.lht.R;
- /**
- * Created by Ly on 2016/11/2.
- */
- public abstract class BaseActivity<V, T extends BasePresenter<V>> extends AppCompatActivity {
- protected T mPresenter;
- private AppBarLayout mAppBar;
- private Toolbar mToolbar;
- private SwipeRefreshLayout mRefreshLayout;
- public Context mContext;
- private boolean mIsRequestDataRefresh = false;
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mContext = this;
- // 同意为空 不是全部的都要实现这个模式
- if (createPresenter() != null) {
- mPresenter = createPresenter();
- mPresenter.attachView((V) this);
- }
- setContentView(provideContentViewId());
- ButterKnife.bind(this);
- mAppBar = (AppBarLayout) findViewById(R.id.app_bar_layout);
- mToolbar = (Toolbar) findViewById(R.id.toolbar);
- if (mToolbar != null && mAppBar != null) {
- setSupportActionBar(mToolbar); //把Toolbar当做ActionBar给设置
- if (canBack()) {
- ActionBar actionBar = getSupportActionBar();
- if (null != actionBar) {
- //设置ActionBar一个返回箭头。主界面没有,次级界面有
- actionBar.setDisplayHomeAsUpEnabled(true);
- }
- if (Build.VERSION.SDK_INT >= 21) {
- //Z轴浮动
- mAppBar.setElevation(10.6F);
- }
- }
- }
- if (isSetRefresh()) {
- setupSwipeRefresh();
- }
- }
- public static void toIntent(Context context, String... str) {
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // 此时android.R.id.home即为返回箭头
- if (item.getItemId() == android.R.id.home) {
- onBackPressed();
- finish();
- return true;
- } else {
- return super.onOptionsItemSelected(item);
- }
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (mPresenter != null) {
- mPresenter.detachView();
- }
- }
- /**
- * 生成下拉刷新
- */
- private void setupSwipeRefresh() {
- mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
- if (null != mRefreshLayout) {
- mRefreshLayout.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimary);
- mRefreshLayout.setProgressViewOffset(true,
- 0,
- (int) TypedValue.applyDimension
- (TypedValue.COMPLEX_UNIT_DIP, 24, getResources()
- .getDisplayMetrics()));
- }
- }
- /**
- * 设置刷新
- *
- * @param requestDataRefresh
- */
- public void setRefresh(boolean requestDataRefresh) {
- if (mRefreshLayout == null) {
- return;
- }
- if (!requestDataRefresh) {
- mIsRequestDataRefresh = false;
- mRefreshLayout.postDelayed(() -> {
- if (mRefreshLayout != null) {
- mRefreshLayout.setRefreshing(false);
- }
- }, 1000);
- } else {
- mRefreshLayout.setRefreshing(true);
- }
- }
- /**
- * 数据刷新
- */
- public void requestDataRefresh() {
- mIsRequestDataRefresh = true;
- }
- /**
- * 推断当前 Activity 是否同意返回
- * 主界面不同意返回,次级界面同意返回
- *
- * @return false
- */
- public boolean canBack() {
- return false;
- }
- /**
- * 推断子Activity是否须要刷新功能
- *
- * @return false
- */
- public Boolean isSetRefresh() {
- return false;
- }
- /**
- * 创建P
- *
- * @return T
- */
- protected abstract T createPresenter();
- /**
- * 用于引入布局文件
- *
- * @return
- */
- abstract protected int provideContentViewId();
- }
- package mvpmaster.lht.com.lht.base;
- import android.content.Context;
- import android.os.Bundle;
- import android.support.v4.app.Fragment;
- import android.support.v4.widget.SwipeRefreshLayout;
- import android.util.TypedValue;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import butterknife.ButterKnife;
- import mvpmaster.lht.com.lht.R;
- /**
- * Created by Ly on 2016/11/2.
- */
- public abstract class BaseFragment<V, T extends BasePresenter<V>> extends Fragment {
- protected Context mContext;
- protected T mPresenter;
- private boolean mIsRequestDataRefresh = false;
- private SwipeRefreshLayout mRefreshLayout;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mContext = getActivity();
- mPresenter = createPresenter();
- mPresenter.attachView((V) this);
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View rootView = inflater.inflate(createViewLayoutId(), container, false);
- ButterKnife.bind(this, rootView);
- initView(rootView);
- if (isSetRefresh()) {
- setupSwipeRefresh(rootView);
- }
- return rootView;
- }
- @Override
- public void onDestroy() {
- super.onDestroy();
- mPresenter.detachView();
- }
- private void setupSwipeRefresh(View view) {
- mRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refresh);
- if (mRefreshLayout != null) {
- mRefreshLayout.setColorSchemeResources(R.color.refresh_progress_1,
- R.color.refresh_progress_2, R.color.refresh_progress_3);
- mRefreshLayout.setProgressViewOffset(true, 0, (int) TypedValue
- .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources().getDisplayMetrics()));
- mRefreshLayout.setOnRefreshListener(this::requestDataRefresh);
- }
- }
- public void requestDataRefresh() {
- mIsRequestDataRefresh = true;
- }
- public void setRefresh(boolean requestDataRefresh) {
- if (mRefreshLayout == null) {
- return;
- }
- if (!requestDataRefresh) {
- mIsRequestDataRefresh = false;
- mRefreshLayout.postDelayed(() -> {
- if (mRefreshLayout != null) {
- mRefreshLayout.setRefreshing(false);
- }
- }, 1000);
- } else {
- mRefreshLayout.setRefreshing(true);
- }
- }
- protected abstract T createPresenter();
- protected abstract int createViewLayoutId();
- protected void initView(View rootView) {
- }
- public Boolean isSetRefresh() {
- return true;
- }
- }
还有其它的一些base,我就不一一上传了。
- 说一下我理解的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了)
- 我们举一个样例,首页那里拿取了知乎的信息,用了一个recyclerview去显示拿到的数据。我们就用它来讲,我先上传一波项目文件夹,不然太懵逼了。
- 我们先看我们的fragment
- package mvpmaster.lht.com.lht.ui.fragment.zhuhu;
- import android.os.Bundle;
- import android.support.v7.widget.LinearLayoutManager;
- import android.support.v7.widget.RecyclerView;
- import android.view.View;
- import android.widget.Toast;
- import butterknife.Bind;
- import mvpmaster.lht.com.lht.R;
- import mvpmaster.lht.com.lht.base.BaseFragment;
- import mvpmaster.lht.com.lht.ui.adapter.ZhiHuAdapter;
- import mvpmaster.lht.com.lht.ui.beanIml.NewsTimeLine;
- /**
- * Created by Ly on 2016/11/2.
- */
- public class ZhiHuFragment extends BaseFragment<ZhiHuContract.ZhiHuView, ZhiHuPresenter> implements ZhiHuContract.ZhiHuView {
- @Bind(R.id.content_list)
- RecyclerView mRlvZhiHu;
- private LinearLayoutManager mLayoutManager;
- private ZhiHuAdapter zhiHuAdapter;
- // 最后一个可见的视图
- private int lastVisibleItem;
- // 是否载入过很多其它
- private boolean isLoadMore = false;
- // 知乎日报须要的下一个參数
- private String time;
- /**
- * 初始化配置
- */
- private void initConf() {
- // 适配器
- zhiHuAdapter = new ZhiHuAdapter(getActivity());
- // manager
- mLayoutManager = new LinearLayoutManager(getActivity());
- mRlvZhiHu.setLayoutManager(mLayoutManager);
- mRlvZhiHu.setAdapter(zhiHuAdapter);
- // 启动自己主动刷新配置
- setDataRefresh(true);
- // 获取第一次的数据
- mPresenter.getDataList();
- // 检測recView的滑动状态
- scrollRecycleView();
- }
- /**
- * recyclerView Scroll listener , maybe in here is wrong ?
- */
- public void scrollRecycleView() {
- mRlvZhiHu.addOnScrollListener(new RecyclerView.OnScrollListener() {
- @Override
- public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
- super.onScrollStateChanged(recyclerView, newState);
- if (newState == RecyclerView.SCROLL_STATE_IDLE) {
- lastVisibleItem = mLayoutManager
- .findLastVisibleItemPosition();
- if (mLayoutManager.getItemCount() == 1) {
- zhiHuAdapter.updateLoadStatus(zhiHuAdapter.getLOAD_MORE());
- return;
- }
- if (lastVisibleItem + 1 == mLayoutManager
- .getItemCount()) {
- zhiHuAdapter.updateLoadStatus(zhiHuAdapter.getLOAD_PULL_TO());
- isLoadMore = true;
- zhiHuAdapter.updateLoadStatus(zhiHuAdapter.getLOAD_MORE());
- mPresenter.getBeforeDateList(time);
- }
- }
- }
- @Override
- public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
- super.onScrolled(recyclerView, dx, dy);
- lastVisibleItem = mLayoutManager.findLastVisibleItemPosition();
- }
- });
- }
- @Override
- public void requestDataRefresh() {
- super.requestDataRefresh();
- setDataRefresh(true);
- mPresenter.getDataList();
- }
- @Override
- protected ZhiHuPresenter createPresenter() {
- return new ZhiHuPresenter(this);
- }
- @Override
- protected int createViewLayoutId() {
- return R.layout.fragment_zhihu;
- }
- @Override
- public void setDataRefresh(boolean refresh) {
- setRefresh(refresh);
- }
- public static ZhiHuFragment newInstance() {
- Bundle args = new Bundle();
- ZhiHuFragment fragment = new ZhiHuFragment();
- fragment.setArguments(args);
- return fragment;
- }
- @Override
- public void loadFinishAndReset(NewsTimeLine newsTimeLine, String time) {
- zhiHuAdapter.resetData(newsTimeLine);
- setDataRefresh(false);
- this.time = time;
- }
- @Override
- public void loadFinishAndAdd(NewsTimeLine newsTimeLine, String time) {
- zhiHuAdapter.addData(newsTimeLine);
- this.time = time;
- }
- @Override
- public void loadFailure() {
- setDataRefresh(false);
- zhiHuAdapter.updateLoadStatus(zhiHuAdapter.getLOAD_FAILURE());
- }
- @Override
- protected void initView(View rootView) {
- super.initView(rootView);
- initConf();
- }
- @Override
- public void TsShow(String msg) {
- Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show();
- }
- }
我们在这个看到一个mPresenter。这个是什么鬼?是从哪里来的?事实上这个就是Presenter的对象了。也是BaseActivity的泛型里面的那个
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">我们点取查看它的引用,发如今这个fragment里面一共被引用了3次。第一次是刚进去页面的时候,第一次读取数据。第二个是下拉载入的时候,读取了下一波的数据。再有一次是上拉刷新的时候。我们又一次刷新了一次页面拿取了最新的一波数据,可是?拿数据的在哪里呢?网络请求呢?在哪里??
- 我们看Presenter里面做的操作吧:
- package mvpmaster.lht.com.lht.ui.fragment.zhuhu;
- import mvpmaster.lht.com.lht.base.BasePresenter;
- import mvpmaster.lht.com.lht.conf.OkHttpCallBack;
- import mvpmaster.lht.com.lht.ui.beanIml.NewsTimeLine;
- /**
- * Created by Ly on 2016/11/2.
- */
- public class ZhiHuPresenter extends BasePresenter<ZhiHuContract.ZhiHuView> implements ZhiHuContract.ZhiHuPresenter {
- private ZhiHuContract.ZhiHuView zhiHuView;
- private ZhiHuContract.ZhiHuModel zhiHuModel;
- public ZhiHuPresenter(ZhiHuContract.ZhiHuView zhiHuView) {
- this.zhiHuView = zhiHuView;
- zhiHuModel = new ZhiHuModel();
- }
- @Override
- public void getDataList() {
- zhiHuModel.getDataList(new OkHttpCallBack<NewsTimeLine>() {
- @Override
- public void onSuccess(NewsTimeLine newsTimeLine) {
- zhiHuView.loadFinishAndReset(newsTimeLine, newsTimeLine.getDate());
- }
- @Override
- public void onFaild(Throwable e) {
- loadError(e);
- zhiHuView.loadFailure();
- }
- @Override
- public void onFinish() {
- }
- });
- }
- @Override
- public void getBeforeDateList(String time) {
- zhiHuModel.getBeforeDateList(time, new OkHttpCallBack<NewsTimeLine>() {
- @Override
- public void onSuccess(NewsTimeLine newsTimeLine) {
- zhiHuView.loadFinishAndAdd(newsTimeLine, newsTimeLine.getDate());
- }
- @Override
- public void onFaild(Throwable e) {
- loadError(e);
- zhiHuView.loadFailure();
- }
- @Override
- public void onFinish() {
- }
- });
- }
- private void loadError(Throwable throwable) {
- throwable.printStackTrace();
- zhiHuView.TsShow(throwable.getMessage());
- }
- }
我们看到有三个ovver的方法。各自是刷新(第一次读取),载入。读取失败 三种情况:我们能够看到,这个类持有了View和Model两个模块,在方法体里面,我们调用了model的方法去做耗时,在结果方法体里面我们调用了view的方法去改动UI,同一时候presenter这个模块又被view持有了,view能够在声明周期里面去调用特定的方法,view和presenter相互沟通。view和model全然隔离,presenter调控model,presenter沟通全局。
一个小框架,基于rx_retrofit2_mvp的更多相关文章
- 利用jdbc简单封装一个小框架(类似DBUtils)
利用jdbc写的一个类似DBUtils的框架 package com.jdbc.orm.dbutils; import java.io.IOException; import java.io.Inpu ...
- mpvue最佳实践 , 美团出的一个小程序框架
看手机微信,看到说美团出了1个小程序框架, mpvue 搜下来试试,看了网上的一个对比 ----------------- 以下为引用 我们对微信小程序.mpvue.WePY 这三个开发框架的主要能 ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(十四)——开发环境容器调试小技巧
之前有很多同学提到如何做容器调试,特别是k8s环境下的容器调试,今天就讲讲我是如何调试的.大家都知道在vs自带的创建项目模板里勾选docker即可通过F5启动docker容器调试.但是对于启动在k8s ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(二十)——Saga框架实现思路分享
今天这篇博文的主要目的是分享一下我设计Saga的实现思路来抛砖引玉,其实Saga本身非常的类似于一个简单的工作流体系,相比工作流不一样的部分在于它没有工作流的复杂逻辑处理机制(比如会签),没有条件分支 ...
- 分析一个类似于jquery的小框架
在网上下了一个类似于jQuery的小框架,分析源码,看看怎么写框架. 选择器Select //用沙箱闭包其整个代码,只有itcast和I暴漏在全局作用域 (function( window , und ...
- 一个可以代替冗长switch-case的消息分发小框架
在项目中,我需要维护一个应用层的字节流协议.这个协议的每条报文都是一个字节数组,数组的头两个字节表示消息的传送方向,第三.四个字节表示消息ID,也就是消息种类,再往后是消息内容.时间戳.校验码等……整 ...
- 2、基于wsgiref模块DIY一个web框架
一 web框架 Web框架(Web framework)是一种开发框架,用来支持动态网站.网络应用和网络服务的开发.这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方 ...
- spring security 一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中 配置的Bean,充分利用了Spring ...
- 任务驱动,对比式学习.NET开发系列之开篇------开源2个小框架(一个Winform框架,一个Web框架)
一 源码位置 1. Winform框架 2. web框架 二 高效学习编程的办法 1 任务驱动方式学习软件开发 大部分人学习软件开发技术是通过看书,看视频,听老师上课的方式.这些方式有一个共同点即按知 ...
随机推荐
- DTrace Probes in HotSpot VM
http://docs.oracle.com/javase/6/docs/technotes/guides/vm/dtrace.html
- 报错:System.NotSupportedException: LINQ to Entities does not recognize the method
报错:System.NotSupportedException: LINQ to Entities does not recognize the method ...... get_Item(Int3 ...
- 内存溢出导致jenkins自动部署到tomcat失败
原文地址:http://openwares.net/java/jenkens_deploy_to_tomcat_error_of_outofmemoryerror.html jenkins自动部署wa ...
- PostgreSQL学习手册(目录)
原文地址:http://www.cnblogs.com/stephen-liu74/archive/2012/06/08/2315679.html 事实上之前有很长一段时间都在纠结是否有必要好好学习它 ...
- JMeter学习(二十三)关联
话说LoadRunner有的一些功能,比如:参数化.检查点.集合点.关联,Jmeter也都有这些功能,只是功能可能稍弱一些,今天就关联来讲解一下. JMeter的关联方法有两种:后置处理器-正则表达式 ...
- python测试开发django-22.admin首页和title修改
前言 django的admin首页默认显示的"Django 管理",title显示的是"Django 站点管理员",这里的文案内容可以修改成自己项目的后台页面内 ...
- Unity中的内存泄漏
在对内存泄漏有一个基本印象之后,我们再来看一下在特定环境——Unity下的内存泄漏.大家都知道,游戏程序由代码和资源两部分组成,Unity下的内存泄漏也主要分为代码侧的泄漏和资源侧的泄漏,当然,资源侧 ...
- spring4 quartz2 集群动态任务
实现定时任务的执行,而且要求定时周期是不固定的.测试地址:http://sms.reyo.cn 生产环境:nginx+tomcat+quartz2.2.1+spring4.2.1 集群. 实现功能:可 ...
- ios之gcd浅析
A.普通的GCD异步运行与主线程更新写法: dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^ ...
- ios之网络异常与正常视图的切换
1. xib中创建两个View 2. View的视图大概如下第一个:View View 第二个:View 3. 代码切换: [self.view addSubview:_redView]; // 会 ...