Android MVP框架 詳細代碼


android mvp的好處,網上一搜一大堆,相對於一開始普通的在activity中處理所有的不管是網絡請求還是頁面渲染,最大的好處是簡潔了,廢話不多說,看代碼

這里網絡請求使用了兩種,一種是自己封裝的okhttp,一種是retrofit+rxjava,可以看出retrofit+rxjava的鏈式調用和普通的okhttp的區別

mvp,m-model 處理數據,v-activity渲染展示,p-persenter 用於連接m和v,其中又引入鍥約類的概念,用於管理這三個所有的接口。

先看代碼,

,為了方便我直接放在一個包里了,可以看到 有TestActivity,(mvp-v),TestModel(mvp-m),TestPersenter(mvp-p),其中TestContract就是契約類,用於管理用到的所有接口,多了一個TestCallback用於使用自己封裝的okhttp回調,使用retrofit+rxjava時可以省略,這其中也有人習慣把TestModel省略,直接在Persenter中處理數據然后在view中返回。

 

 

先看契約類,其中BaseView可以提取一些公共的方法

 

public interface TestContract {

    interface TestModel{
        void getData(String id,TestCallback callback);
        Observable<HomePage> getData();
    }

    interface TestPersenter{
        void getData(String id);
    }
    interface TestView extends BaseView {
void SetData(HomePage homePage);
}
 }
public interface BaseView {

    void Toast(String s);

    /**
     * 綁定Android生命周期 防止RxJava內存泄漏
     *
     * @param <T>
     * @return
     */
    <T> AutoDisposeConverter<T> bindAutoDispose();

}

 

可以清楚的看到,model,persenter,view使用到的接口。

再看activity中,implements  TestContract.TestView接口,必須實現接口中的方法----SetData,定義了一個按鈕,一個TextView,點擊按鈕,獲取數據,顯示在TextView中,其中TestPersenter testPersenter = new TestPersenter(this);體現了persenter的連接作用,獲取到實例,調用persenter中的getData方法,

 
         
public class TestActivity extends BaseActivity implements TestContract.TestView {

TestPersenter testPersenter = new TestPersenter(this);

@BindView(R.id.button)
Button button;
@BindView(R.id.testview)
TextView testview;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
ButterKnife.bind(this);

button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
testPersenter.getData("1");
}
});
}


@Override
public void SetData(HomePage homePage) {
testview.setText(homePage.getMessage());
}

@Override
public void Toast(String s) {
super.Toast(s);

}
}
 
public class BaseActivity extends AppCompatActivity implements BaseView {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base2);
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        getSupportActionBar().hide();
        ImmersionBar.with(this)
                .statusBarColor(R.color.bar)     //狀態欄顏色,不寫默認透明色
                .statusBarDarkFont(true) //原理:如果當前設備支持狀態欄字體變色,會設置狀態欄字體為黑色,如果當前設備不支持狀態欄字體變色,會使當前狀態欄加上透明度,否則不執行透明度
                .fitsSystemWindows(true)
                .keyboardEnable(true)
                .init();

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 必須調用該方法,防止內存泄漏
        ImmersionBar.destroy(this,null);
    }
    /**
     * 綁定生命周期 防止MVP內存泄漏
     *
     * @param <T>
     * @return
     */
    @Override
    public <T> AutoDisposeConverter<T> bindAutoDispose() {
        return AutoDispose.autoDisposable(AndroidLifecycleScopeProvider
                .from(this, Lifecycle.Event.ON_DESTROY));
    }

    @Override
    public void Toast(String s) {

    }
}

 

TestPersenter,首先implements 接口,實現接口中的方法---getData,其次拿到了model和view,在getData方法中,調用model獲取數據,調用view的setData方法展示數據到頁面,從這里也可以看出persenter的連接作用,連接model和view。

public class TestPersenter implements TestContract.TestPersenter{

    TestContract.TestModel model ;
    TestContract.TestView testView;

    public TestPersenter(TestContract.TestView testView) {
        this.testView = testView;
        this.model = new TestModel();
    }

    @Override
    public void getData(String id) {
        model.getData("1", new TestCallback() {
            @Override
            public <T> void success(T enty) {
                testView.SetData((HomePage) enty);
            }

            @Override
            public void error(String msg) {
                
            }
        });
    }
}

model:同樣implements接口,實現接口中的方法getData,第一個方法是使用自己封裝的okhttp網絡類,在這里就看出TestCallback 的作用了,訪問接口獲取數據后,通過TestCallback 返回,TestCallback 中只定義了兩個簡單的,一個成功時的回調,一個失敗時的回調

 
         
public class TestModel implements TestContract.TestModel {

@Override
public void getData(String id, TestCallback callback) {
new OkHttpUtil().getJson(HttpUrl.homePage, new OkHttpUtil.HttpCallBack() {
@Override
public void onSusscess(String data) throws JSONException, ParseException {
HomePage homePage = new Gson().fromJson(data,HomePage.class);
if(homePage.isSuccess()){
callback.success(homePage);
}else{
callback.error(homePage.getMessage());
}
}

@Override
public void onError(String meg) {
super.onError(meg);
callback.error(meg);
}
});
}

@Override
public Observable<HomePage> getData() {
       return RetrofitClient.getInstance().getApi().GetData();
    }
}
 
public interface TestCallback {
    <T> void success(T enty);

    void error(String msg);
}

使用retrofit+rxjava,可以看到,省略了TestCallback回調,直接鏈式調用,onNext中調用了view的setData方法顯示數據。

public class TestPersenter implements TestContract.TestPersenter{

    TestContract.TestModel model ;
    TestContract.TestView testView;

    public TestPersenter(TestContract.TestView testView) {
        this.testView = testView;
        this.model = new TestModel();
    }

    @Override
    public void getData(String id) {
//        model.getData("1", new TestCallback() {
//            @Override
//            public <T> void success(T enty) {
//                testView.SetData((HomePage) enty);
//            }
//
//            @Override
//            public void error(String msg) {
//
//            }
//        });
 model.getData()
            .compose(RxScheduler.Obs_io_main())
            .to(studyView.bindAutoDispose())
            .subscribe(new Observer<HomePage>() {
                @Override
                public void onSubscribe(@NonNull Disposable d) {

                }

                @Override
                public void onNext(@NonNull HomePage homePage) {
                    testView.SetData(homePage);
                }

                @Override
                public void onError(@NonNull Throwable e) {
           
) } @Override public void onComplete() { } }); } }



retrofit的使用到的方法

 

 

 

public interface APIService {

/**
* 首頁數據
* @return
*/
@GET("app/home_page/queryList")
Observable<HomePage> GetData();

}
public class RetrofitClient {

    private static volatile RetrofitClient instance;
    private APIService apiService;
    private String baseUrl = "****";
    private Retrofit retrofit;
    private OkHttpClient okHttpClient;

    private RetrofitClient() {
    }

    public static RetrofitClient getInstance() {
        if (instance == null) {
            synchronized (RetrofitClient.class) {
                if (instance == null) {
                    instance = new RetrofitClient();
                }
            }
        }
        return instance;
    }

    /**
     * 設置Header
     *
     * @return
     */
    private Interceptor getHeaderInterceptor() {
        return new Interceptor() {
            @Override
            public Response intercept(@NonNull Chain chain) throws IOException {
                Request original = chain.request();
                Request.Builder requestBuilder = original.newBuilder();
                //添加Token
//                        .header("token", "");
                Request request = requestBuilder.build();
                return chain.proceed(request);
            }
        };

    }

    /**
     * 設置攔截器 打印日志
     *
     * @return
     */
    private Interceptor getInterceptor() {

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        //顯示日志
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        return interceptor;
    }

    public OkHttpClient getOkHttpClient() {
        if (okHttpClient == null) {
            //如果為DEBUG 就打印日志
            if (BuildConfig.DEBUG) {
                okHttpClient = new OkHttpClient().newBuilder()
                        //設置Header
                        .addInterceptor(getHeaderInterceptor())
                        //設置攔截器
                        .addInterceptor(getInterceptor())
                        .build();
            } else {
                okHttpClient = new OkHttpClient().newBuilder()
                        //設置Header
                        .addInterceptor(getHeaderInterceptor())
                        .build();
            }

        }

        return okHttpClient;
    }

    public APIService getApi() {
        //初始化一個client,不然retrofit會自己默認添加一個
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    //設置網絡請求的Url地址
                    .baseUrl(baseUrl)
                    //設置數據解析器
                    .addConverterFactory(GsonConverterFactory.create())
                    //設置網絡請求適配器,使其支持RxJava與RxAndroid
                    .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                    .client(getOkHttpClient())
                    .build();
        }
        //創建—— 網絡請求接口—— 實例
        if (apiService==null){
            apiService = retrofit.create(APIService.class);
        }

        return apiService;
    }


}

 

public class RxScheduler {

    /**
     * 統一線程處理
     *
     * @param <T> 指定的泛型類型
     * @return FlowableTransformer
     */
    public static <T> FlowableTransformer< T, T> Flo_io_main() {
        return new FlowableTransformer<T, T>() {
            @Override
            public Publisher<T> apply(Flowable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

    /**
     * 統一線程處理
     *
     * @param <T> 指定的泛型類型
     * @return ObservableTransformer
     */
    public static <T> ObservableTransformer<T, T> Obs_io_main() {
        return new ObservableTransformer<T, T>() {
            @Override
            public ObservableSource<T> apply( Observable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }

}
public interface BaseView {

    void Toast(String s);

    /**
     * 綁定Android生命周期 防止RxJava內存泄漏
     *
     * @param <T>
     * @return
     */
    <T> AutoDisposeConverter<T> bindAutoDispose();

}
 //okhttp3
    implementation 'com.squareup.okhttp3:okhttp:4.2.0'
    implementation "com.squareup.okhttp3:logging-interceptor:3.10.0"
    implementation 'com.google.code.gson:gson:2.8.6'

    //retrofit2
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'

    //AutoDispose解決RxJava內存泄漏
    implementation 'com.uber.autodispose2:autodispose:2.0.0'
    implementation 'com.uber.autodispose2:autodispose-android:2.0.0'
    implementation 'com.uber.autodispose2:autodispose-lifecycle:2.0.0'
    implementation 'com.uber.autodispose2:autodispose-androidx-lifecycle:2.0.0'
  // 基礎依賴包,必須要依賴
implementation 'com.gyf.immersionbar:immersionbar:3.0.0-beta07'
// fragment快速實現(可選)
implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0-beta07'

 

至此,mvp框架結束,mvp增加了接口,使頁面和數據處理分開,層次分明,后期好維護。在較小項目中,就幾個頁面,不必使用框架,也不必為了框架而使用,適合項目的才是最好的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM