浅学开发模式----MVP模式和使用Retrofit和RxJava使用

本文深入浅出地介绍了MVP设计模式及其与Retrofit和RxJava的结合应用,通过示例展示了如何利用这些技术进行解耦合开发,提高代码的可维护性和扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在学习开发模式中的MVP模式,看了鸿洋大神的一篇MVP浅学http://blog.youkuaiyun.com/lmj623565791/article/details/46596109【鸿洋大神的mvp介绍】,我自己也知道MVP开发模式简直好用到不行,完全能够知道自己错误是在哪里,逻辑还很清晰,看着以前写的代码简直痛苦的要死,自从学会了这个模式后感觉像是在编码界得到了新生一样--------爽

很久没有看到了这个博客这时看见已经有很多人阅读但是对于我这种不怎么说话的,和第一个词使用csdn的人看见我这种模式都是望而生畏吧,但是我坚信如果是很想学习的人会把我的代码一个一个粘贴复制的话,是一定能跑起来的。这里我从新结束一些mvp模式希望真正的对你起作用。

retrofit使用详细介绍:http://blog.youkuaiyun.com/lmj623565791/article/details/51304204鸿洋大神

RxJava使用详细介绍:http://www.jianshu.com/p/64aa976a46behttp://www.jianshu.com/u/c50b715ccaeb

为retrofit+RxJava添加下面的依赖(这里是RxJava1)

compile 'com.squareup.retrofit2:retrofit:2.0.2'
	compile 'com.squareup.retrofit2:converter-gson:2.0.2'
	compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'

	compile 'io.reactivex:rxjava:1.0.14'
	compile 'io.reactivex:rxandroid:1.0.1'
	compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'


这里是RxJava2依赖
//retrofit
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    //Gson converter
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    //RxJava2 Adapter
    compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
    //okhttp
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
    compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
    compile 'io.reactivex.rxjava2:rxjava:2.0.1'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'


	
mvp说真话懂得人不难,不懂的人第一次看见这种写法估计都是头大了这次我来一次极其简单方式来讲解希望能懂。
 
 
  • View 对应于Activity,负责View的绘制以及与用户交互
  • Model 依然是业务逻辑和实体模型
  • Presenter 负责完成View于Model间的交互
从上面可以看出来mvp各个模块的功能主要不就是为了解决解耦吗,说直白点不就是给View层控件有数据吗?
在说直白点不就是在model中拿到下载的数据?怎么拿到呢?不就是在Persenter层创建Model的实例在调用Model方法获取数据。
获取数据之后不就是在调用View的接口把拿到的数据放入方法中(用到接口回调)...具体我们来看我自己写的一个极其简单例子
先看整体图

我们先来看Model层这里我是模拟从服务器拿到数据
//modle就是为了实现从服务器拿到数据
public class Modle {
    private Modle mModle;

    public String  getData(){
        return "获取数据";
    }
}
getData()不就是一个从服务器拿到的数据吗?然后在Persenter层创建Model的实例调用getData()方法不就是拿到数据了吗?
再来看Persenter层
public class Persenter {
    private Modle mModle;//
    private View mView;//

    public Persenter(View view) {
        mView = view;
        mModle = new Modle();//在构造函数中直接初始化Model的实例
    }
    public Persenter() {
    }

    public void getData(){
        mView.getData(mModle.getData());//把数据方法接口View的getData()中
    }
}
从上面的代码可以看出我是不是一开始就创建了两个字段分别为mModle和mView(这里的view就是为了实现那个类继承了他就传入那个对象进来)
在构造函数中直接初始化Model,写一个方法把从Model层获得数据放入View中,View中的getData()是不是有数据了(接口回调)。
在来View层(简单不行)
public interface View {
    void getData(String data);
}
就一个接口一个方法
然后我们把那个Activity需要这个数据那么就把那个Activity继承View不就拿到了数据?
再来看Activity
public class MainActivity extends AppCompatActivity implements View {
    private TextView mTextView;
    private Persenter mPersenter;//创建Persentershili
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView= (TextView) findViewById(R.id.text);

        mPersenter=new Persenter(this);//创建Persenter实例
        mPersenter.getData();//调用方法
    }

    @Override
    public void getData(String data) {//这里的data就有数据我们直接把它setText中去就有数据了。简单粗暴
        mTextView.setText(data);
    }
然后在结合Retrofit+RxJava来使用
如果大家不懂retrofit和Rxjava请到上面去看怎么使用这里不过多解释了。
请看代码

我们只要把retrofit封装成到一个类中只管调用不就行了吗?
这里我们来看加上RxJava+Retrofit后的代码
现在看整体图

同理上面的图和最开始的时候的图没有多大的区别
1.我们先把Retrofit请求数据操作写在一个类中进行简单的封装看代码
API
public interface API {
    @GET("ProductBrand")
    Observable<Bean>getData();
}
Bean文件你们就自己根据这个接口去生成吧
http://api.shiandianping.com/api/sourceAndroidDianPing/v1.0/ProductBrand
ConStans
public class Constans {
    public static final String URL_HEAD = "http://api.shiandianping.com";

    /**
     * 请求来源
     */
    public static final String URL_SOURCE = "sourceAndroidDianPing";

    /**
     * URL
     */
    public static final String BASE_URL = URL_HEAD+"/api/" + URL_SOURCE + "/v1.0/";
}
这些准备好我们就开始写Retrofit的数据请求操作
public class Http {
    //retrofit的操作
    public static Retrofit getRetrofit(){
        OkHttpClient.Builder builder=new OkHttpClient.Builder();
        builder.readTimeout(10, TimeUnit.SECONDS);
        builder.connectTimeout(9,TimeUnit.SECONDS);
        if (BuildConfig.DEBUG){
            HttpLoggingInterceptor interceptor=new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(interceptor);
        }
        return new Retrofit.Builder()
                .baseUrl(Constans.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(builder.build())
                .build();
    }
}

2.这些做完我们就来看model中做了哪些操作和上面第一例子有什么区别
public class IBaseModel<T extends BasePersenter> {
    public T presenter;

    public IBaseModel(T presenter) {
        this.presenter = presenter;
    }
}

//modle就是为了实现从服务器拿到数据
public class Modle extends IBaseModel<Persenter>{
    private Modle mModle;

    public Modle(Persenter presenter) {
        super(presenter);
    }

    public void getData(){
        API api = Http.getRetrofit().create(API.class);
        api.getData()//RxJava方便体现出来了
                .subscribeOn(Schedulers.newThread())//把ObServable的操作(网络请求)运行在子线程
                .observeOn(AndroidSchedulers.mainThread())//把observer的操作(也就是给UI数据)运行在主线程
        .subscribe(new Observer<Bean>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(Bean value) {
                presenter.getDataSuccess(value);//拿到数据
            }

            @Override
            public void onError(Throwable e) {
                presenter.getDataFailure(e.getMessage());
            }

            @Override
            public void onComplete() {

            }
        });
    }
}
3.在onNext()不就是有了数据我们只要把数据放入presenter.getDataSuccess()不就是有了数据
在来看Presenter
public class BasePersenter {
}
public class Persenter extends BasePersenter{
    private Modle mModle;
    private View mView;

    public Persenter(View view) {
        mView = view;
        mModle = new Modle(this);
    }

    public void getData(){
        mModle.getData();
    }
    public void getDataSuccess(Bean bean){
        mView.getDataSuccess(bean);//是不是和上面的第一个例子很像?不错这里就是调用接口回调吧数据入View这接口的方法中
    }
    public void getDataFailure(String s){
        mView.getDataFailure(s);
    }
4.在Activity中调用拿到数据
public class MainActivity extends AppCompatActivity implements View {
    private TextView mTextView;
    private Persenter mPersenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView= (TextView) findViewById(R.id.text);

        mPersenter=new Persenter(this);
        mPersenter.getData();
    }

    @Override
    public void getDataSuccess(Bean data) {
        mTextView.setText(data.getMssage());
    }

    @Override
    public void getDataFailure(String s) {

    }
}
好的在这里RxJava+Retrofit就这结束了希望对你有所帮助好好看第一个例子来结合第二个例子你会有很多收获我觉得希望对你又说帮助
下面这你们可以不看了这是我以前写的例子有些不完整了。

列表截图:
 
BaseActivity:
 
/**
定义一个Activity基类这里使用<T extends BasePresenterI,V>中T extends BasePresenterI主要是获取到Presenter类的实例,
V:获取JavaBean对象(如:传一个GankBean)继承BaseView<V>这里给的是泛型,在主函数中自己给定想要的什么数据类型的泛型*/
public abstract class BaseActivity<T extends BasePresenterI,V> extends AppCompatActivity implements BaseView<V> {
    public T mPresenter;//定义一个Presenter类
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutId());//设置XML文件

        if (mPresenter==null){//判断是否为空
            mPresenter=getPresenter();获取presenter
        }
        initData();
        initView();
    }

    protected abstract int getLayoutId();
    protected abstract void initData();
    protected abstract void initView();

    public T getPresenter() {
        return null;
    }

    @Override
    protected void onDestroy() {
        mPresenter.unSubcrible();//解除RxJava的订阅
        super.onDestroy();
    }
}

BasePresenter:

/**这里的泛型是规定要那个在使用它
public class BasePresenter<T extends BaseView> implements BasePresenterI{
    public T mView;
    public Context context;
    public CompositeSubscription mCompositeSubscription;//获取一个被订阅者的容器
    
     //解除订阅
    @Override
    public void unSubcrible() {
        if (mCompositeSubscription!=null){//判断容器是否为空
            mCompositeSubscription.unsubscribe();
            mView=null;
            context=null;
        }
    }
//添加订阅者
    public void addCompositeSubscription(Subscription s){
        if (mCompositeSubscription==null){
            this.mCompositeSubscription=new CompositeSubscription();
        }
        mCompositeSubscription.add(s);

    }
	//判断是否有网络这里没有使用它。
    @Override
    public boolean checkNetwork() {
        ConnectivityManager connectivityManager = (ConnectivityManager) MyAppliction.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        if(connectivityManager!=null){
            NetworkInfo info = connectivityManager.getActiveNetworkInfo();
            if(info!=null&&info.isConnected()){
                if (info.getState()==NetworkInfo.State.CONNECTED)
                    return true;
            }
        }
        return false;
    }

}

BasePresenterI

public interface BasePresenterI {
    void unSubcrible();
     boolean checkNetwork();
}

BaseView:
//这里泛型主要是为了泛型的数据类型做准备
public interface BaseView<T> {
   public void getData( T datas);
}

主函数MainActivity
//这里的BaseActivity<GanksPresenter, GanksBean>就是看那个Presenter在使用然后获取当前presenter对象
public class MainActivity extends BaseActivity<GanksPresenter, GanksBean> implements ConstrctValues.Gansk {
    private TextView mTextView;
    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

	//让其获取数据的函数运行在主线程
    @Override
    protected void initData() {
        mPresenter.getSurroceData();
    }

    @Override
    protected void initView() {
        mTextView= (TextView) findViewById(R.id.msg);
    }


   //就是去网络下载的数据应用于:接口回调获得数据
    @Override
    public void getData(GanksBean datas) {
        if (datas!=null){
            mTextView.setText(datas.toString());
        }
    }
	//获得当前的presenter对象
    @Override
    public GanksPresenter getPresenter() {
        return new GanksPresenter(this);
    }

    @Override
    protected void onDestroy() {
        mPresenter.unSubcrible();
        super.onDestroy();
    }
}

public interface ConstrctValues {
	//直接给BaseView是那个类型
    public interface Gansk extends BaseView<GanksBean>{};

    public  interface Presenter{
        void getSurroceData();
    }
}


public class MyAppliction extends Application {
    public static MyAppliction myAppliction;

    @Override
    public void onCreate() {
        super.onCreate();
        myAppliction=this;
    }

    public static Context getContext(){
        return myAppliction.getApplicationContext();
    }
}
 
Http中
ConstantValues :定义api
public class ConstantValues {

    /*public static boolean ISUPLOAD = false;
    public static final String packageName = "com.android.mvp";
    public static final String MAIN_HTML = "http://www.shiandianping.com";*/




    // 正式服务器
    public static final String URL_HEAD = "http://api.shiandianping.com";

    /**
     * 请求来源
     */
    public static final String URL_SOURCE = "sourceAndroidDianPing";

    /**
     * URL
     */
    public static final String BASE_URL = "/api/" + URL_SOURCE + "/v1.0/";

//    public static final String PATH="api/sourceAndroidDianPing/v1.0/ProductBrand";

//    http://api.shiandianping.com/api/sourceAndroidDianPing/v1.0/ProductBrand


    /**
     * 首页
     * */

    //首页轮播图
    //public static final String Home_Banner=BASE_URL+"Banner";

    //首页产品类别
//    public static final String Home_ProductBrand=BASE_URL+"ProductBrand";
//    public static final String Home_ProductBrand1=URL_HEAD+PATH;


    //首页社区
    //public static final String HOME_Posts=BASE_URL+"posts/GetHeatPost";

    //首页专题
    //public static final String Home_SpecialTopic=BASE_URL+"SpecialTopic";
    //专题详情
   // public static final String SpecialInfo=BASE_URL+"SpecialTopic";

RxJava+retrofit的配合使用

GanksAPI :定义方法获取数据
public interface GanksAPI {
    @GET(ConstantValues.BASE_URL+"{ProductBrand}")
    Observable<GanksBean> observable(@Path("ProductBrand")String ProductBrand);
}
//使用单例模式获取Http的实例
public class Http {
    private static Http http=null;
    private Retrofit mRetrofit;
    private GanksAPI ganksAPI;
    public static Http getInstance(){
        if (http==null){
            http=new Http();
            return http;
        }
        return null;
    }

    Http(){
	//retrofit的使用
        OkHttpClient client=new OkHttpClient();
        mRetrofit=new Retrofit.Builder()
                .baseUrl(ConstantValues.URL_HEAD)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
       this.ganksAPI=mRetrofit.create(GanksAPI.class);
    }

	//返回一个Obserable(被观察者)
    public GanksAPI getGanksAPI(){
        return ganksAPI;
    }
}

model中主要是从网络获取数据下载这里是使用retrofit进行数据下载,RxJava把数据回抛到主线程
public class GankModel {
    public Observable<GanksBean> getObservable(){
        return Http.getInstance().getGanksAPI().observable("ProductBrand").subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
    }
}

presenter中:
public interface ConstrctValues {
    public interface Gansk extends BaseView<GanksBean>{};

    public  interface Presenter{
        void getSurroceData();
    }
}

	//这里泛型主要是规定数据类型的形式
public class GanksPresenter extends BasePresenter<ConstrctValues.Gansk> implements ConstrctValues.Presenter {
	//获取一个BaseView的对象
    private ConstrctValues.Gansk ganksBean;
	//获取一个model对象
    private GankModel gankModel;

    public GanksPresenter(ConstrctValues.Gansk ganksBean) {
        this.ganksBean = ganksBean;
        this.gankModel=new GankModel();
	//这里必须把BasePresenter的mView赋值否则回报空指针异常,被坑了好几次这里 注意了
        mView=this.ganksBean;
    }

    @Override
    public void getSurroceData() {
	//将Observable添加容器中
        addCompositeSubscription(gankModel.getObservable().subscribe(new Action1<GanksBean>() {
            @Override
            public void call(GanksBean ganksBean) {
		//将数据放入接口的方法中在主MainActivity中就有获取的方法
                mView.getData(ganksBean);
                Log.e("tag","sssss"+ganksBean.toString());
            }
        }));
    }
}





 

	

Cross-Attention指的是Transformer架构中的一种注意力机制,它用于混合两个不同嵌入序列的注意力。这两个序列必须具有相同的维度,并且可以是不同的模式形态,比如文本、声音、图像等。在Cross-Attention中,一个序列作为输入的Q,定义了输出的序列长度,而另一个序列提供输入的KV。 Cross-Attention与Self-Attention不同之处在于,Cross-Attention的输入来自不同的序列,而Self-Attention的输入来自同一个序列。但除此之外,它们的基本原理是一致的。在Transformer中,Cross-Attention通常是指编码器解码器之间的交叉注意力层。在这一层中,解码器会对编码器的输出进行注意力调整,以获得与当前解码位置相关的编码器信息。具体的计算过程包括:编码器输入(通常是来自编码器的输出)解码器输入(已生成的部分序列)被分别表示为enc_inputsdec_inputs。解码器的每个位置会生成一个查询向量(query),用来在编码器的所有位置进行注意力权重计算。编码器的所有位置会生成一组键向量(keys)值向量(values)。通过对查询向量键向量进行点积操作,并通过softmax函数获得注意力权重。注意力权重与值向量相乘,并对结果进行求,得到编码器调整的输出。这样,Cross-Attention机制帮助解码器能够有效地建模当前生成位置的上下文信息。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【科研】浅学Cross-attention?](https://blog.youkuaiyun.com/MengYa_Dream/article/details/126688503)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [交叉注意力机制CrossAttention](https://blog.youkuaiyun.com/m0_63097763/article/details/132293568)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值