Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android設計之美:MVP模式創建輪播圖(Banner)

Android設計之美:MVP模式創建輪播圖(Banner)

編輯:關於Android編程

准備工作:

利用github第三方添加輪播圖 基於MVP模式搭建架構 調試

添加輪播圖:

可參考:github輪播圖Banner

添加依賴:

//添加Retrofit的依賴和Glide的依賴和banner的依賴
compile 'com.youth.banner:banner:1.4.1' 
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.github.bumptech.glide:glide:3.7.0'

在AndroidManifest.xml中添加用戶權限:


 


banner在Xml文件的布局:

//頭部的地方添加:
 xmlns:banner="http://schemas.android.com/apk/res-auto"
 //Banner布局頁面

MVP邏輯分析:

簡單的的布局和設置就准備就緒了,那麼接下來就開始寫邏輯代碼了,以下是我的代碼結構圖:

\

MVP的結構圖示:

代碼具體分析

在一個包裡面創建上面的九個類:

按道理來說,應該只有M、V、P三個類的,為什麼出現了九個類呢?下面我就一 一 解答,其實很簡單,主要的是M、V、P這三個類,其它 的類之是起了輔助作用,要麼是封裝方法,要麼是適配器。

Adapter :
適配器

Banner:
實體類,可以用GsonFormat自生成,也可以手寫。

Contract :
分別將M(Model)、V(View)、P(presenter)裡面的方法抽象分離,放到Contract這個公共接口中來,這樣設計的好處是利於修改高內聚,低耦合。

HttpUtils:
看以看我的代碼注釋,講解的很清楚,其實簡單點來說,就是將retrofit裡面的網絡加載和數據解析的方法封裝了起來,這樣增強代碼的可移植性,也簡單方便,不用你每次都用以下五步來使用retrofit,直接將2-5步封裝了起來:

定義一個接口(封裝URL地址和數據請求)

實例化Retrofit

通過retrofit實例創建接口服務對象

接口服務對象調用接口中方法,獲得Call對象

Call對象執行請求(異步、同步)

View(MainActivity):
Fragment也就是MVP中的V,同樣的Activity也屬於View。
用於調用presenter的方法來傳遞拼接的Map params。最終presenter將View層得到的params傳給model,解析JSON。

Model(MainModel) :
Model簡單點講:作用就是加載網絡數據,得到,然後將得到的網絡解析的bean實體數據,以接口回調的方式返還給Presenter層。 Presenter(MainPresenter) :
Presenter接口回調,得到實體bean的list集合,然後將list集合傳給View層,因為View才能操作數據。然後加載適配器得到最終的頁面顯示。 RetrofitService :
接口回調的方法 參見 三分鐘教你學會Retrofit解析JSON

UrlConfig:
將JSON字符拆分,具體原理參考 三分鐘教你學會Retrofit解析JSON

同樣的學習MVP,可參考大神鴻洋的CSDN: 淺談 MVP in Android

分析就到這,如果有啥具體不懂的可以留言,我會一 一幫你解決,閒話不多講,直接上代碼。

代碼示例:

我是利用插件GsonFormat來直接生成的實例對象,有興趣的同學可以自行Google。所以在實體bean的Banner類中:

//構建bean類對象
public class Banner {
    private Object searchHotKey;
    private List adList;
    public Object getSearchHotKey() {
        return searchHotKey;
    }
    public void setSearchHotKey(Object searchHotKey) {
        this.searchHotKey = searchHotKey;
    }
    public List getAdList() {
        return adList;
    }
    public void setAdList(List adList) {
        this.adList = adList;
    }
    public static class AdListBean {
        private int UrlClass;
        private String address;
        private String cName;
        private int cStatus;
        private String imgUrl;

        public int getUrlClass() {
            return UrlClass;
        }
        public void setUrlClass(int UrlClass) {
            this.UrlClass = UrlClass;
        }

        public String getAddress() {
            return address;
        }

        public void setAddress(String address) {
            this.address = address;
        }

        public String getCName() {
            return cName;
        }

        public void setCName(String cName) {
            this.cName = cName;
        }

        public int getCStatus() {
            return cStatus;
        }

        public void setCStatus(int cStatus) {
            this.cStatus = cStatus;
        }

        public String getImgUrl() {
            return imgUrl;
        }

        public void setImgUrl(String imgUrl) {
            this.imgUrl = imgUrl;
        }
    }
}

在Constract類中:

public class Contract {
    public  interface  View{
        //訪問網絡數據成功
        void getDataSuccessful(List adListBeen);
        //訪問網絡數據失敗
        void getDataFail(String error);
                             }
    public  interface  Model{
        //傳入參數,獲得數據
        Void getBannerData(Map params,Callback callback);
                             }
    public  interface  Presenter{
        //將params傳入到presenter中去,因為View與Model交互,所以只能
        //傳給Presenter,然後再調用上面的那個方法,將params傳入到上面的方法中去
        void  putBannerData(Map params);
                                }
}

在View類中:

//MainActivity為View,只能與Presenter之間相互溝通。在View中必須實例化Presenter。

public class MainActivity extends AppCompatActivity implements Contract.View {
    private com.youth.banner.Banner  banner;
    private  Contract.Presenter mPresenter;
    private  Map params=new HashMap<>();
    private List bannerImgUrl=new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        banner= (com.youth.banner.Banner) findViewById(R.id.banner);
        //向下轉型,父類引用指向子類對象,實例化Presenter
        mPresenter=new MainPresenter(this);
        //傳遞拼接字符串地址到Presenter
        initPresenter();

    }

    //拼接字符,將拼接的結果傳入Presenter,最終傳入Model,利用Model網絡請求和解析JSON網址。
    private void initPresenter() {
        params.put(UrlConfig.Key.V,UrlConfig.DefaultValue.V);
        mPresenter.putBannerData(params);
    }

    //對banner進行具體的設置,詳情代碼講解請參考-----> github輪播圖Banner(上面有我貼出的網址)
    private void initBanner() {
        banner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR_TITLE);
        banner.setDelayTime(3000);
        banner.setBannerAnimation(Transformer.DepthPage);
        banner.setImageLoader(new ImageLoader() {
            @Override
            public void displayImage(Context context, Object path, ImageView imageView) {
                Glide.with(context).load(path).into(imageView);
            }
        });
        banner.setImages(bannerImgUrl);
        banner.start();

       /* 因為我是在ViewPager裡面的其中一個fragment中嵌套的Banner,所以需要對bannerImgUrl
        進行清除,不然會出現很多不必要的麻煩,比如我輪播圖會多出很多小圓點。*/
        bannerImgUrl.clear();
    }

    @Override
    public void getDataSuccessful(List adListBeen) {
        //將圖片網址添加到bannerImgUrl集合中
            for (Banner.AdListBean list:adListBeen){
                bannerImgUrl.add(list.getImgUrl());
            }
        //調用輪播圖方法,最終達到輪播的效果
        initBanner();
    }

    @Override
    public void getDataFail(String error) {
        Log.i("TAG","----錯誤是-----"+error);
    }


}

在Presenter類中:

/*MainPresenter為Presenter,能夠與Model和View兩個之間相互溝通,
在Presenter必須實例化View和Model*/
public class MainPresenter implements  Contract.Presenter {
    private List listBeen;
    private  Contract.View mView=new MainActivity();
    private  Contract.Model mMoedl=new MainModel();

    public MainPresenter(Contract.View mView) {
        //利用構造函數,傳入View
        this.mView = mView;
    }


    @Override

    //調用方法,傳入params的拼接字符
    public void putBannerData(Map params) {
        //調用方法,傳入params,接口回調得到response實體類,完成Presenter和Model之間的交流。
        mMoedl.getBannerData(params, new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                //具體得到實體類中的list集合
                listBeen=response.body().getAdList();
                //調用View中的方法,傳入list集合。完成Presenter和View之間的交流。
                mView.getDataSuccessful(listBeen);
            }

            @Override
            //加載數據失敗
            public void onFailure(Call call, Throwable t) {
                mView.getDataFail(t.getMessage());
            }
        });
    }
}

在Model類中:

//MainModel為Model,只能與Presenter之間相互溝通。
public class MainModel implements Contract.Model {
    @Override
    public Void getBannerData(Map params, Callback callback) {
        //調用封裝好的Retrofit工具類中的網絡解析方法,傳入各個參數,利用接口回調得到解析後的實體bean
        HttpUtils.getSingletion().getBannerData(UrlConfig.Path.BASEURL,params,callback);
        return null;
    }
}

在封裝的工具類HttpUtil中:

//利用單例模式,封裝的Retrofit的網絡請求和解析方法
public class HttpUtils {
    //創建HttpUtils對象
    private static volatile HttpUtils singletion;
    private Retrofit mRetrofit;
    private RetrofitService mRetrofitService;
    private HttpUtils(){

    }
    public static HttpUtils getSingletion(){
        if(singletion==null){
            synchronized (HttpUtils.class){
                if(singletion==null){
                    singletion=new HttpUtils();
                }
            }
        }
        return singletion;
    }
    //自定義retrofit實例
    private Retrofit createRetrofit(String baseUrl){
        return new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
    /**
     *創建gson實例,用於retrofit解析返回的結果
     */
    private Gson createGson(){
        Gson gson=new GsonBuilder()
                .serializeNulls()
                .create();
        return gson;
    }

    /**
     * 創建網絡接口的實例
     *
     * @return
     */
    private RetrofitService createPresent(){
        RetrofitService mRetrofitService=mRetrofit.create(RetrofitService.class);
        return mRetrofitService;
    }
            //創建你需要的解析的方法,傳入參數,即可解析得到Call的實例對象
    public  void  getBannerData(String baseUrl, Map params, Callbackcallback){
        mRetrofit=createRetrofit(baseUrl);
        mRetrofitService=createPresent();
        Call call=mRetrofitService.getData(params);
        call.enqueue(callback);
    }
}

在RetrofitService接口中:


//定義接口回調方法,字符串拼接規則如下圖
public interface RetrofitService {
    @GET(UrlConfig.Path.BannerURL)
    Call getData(@QueryMap Map params);

}

具體參考我的上篇Blog : 三分鐘教你學會Retrofit解析JSON
在UrlConfig類中:


//JSON字符的拆分>http://blog.csdn.net/u010312949/article/details/52776368
public class UrlConfig {

    //http://www.syby8.com/apptools/indexad.aspx?v=34

    public static class Path{

        public  static  final  String BASEURL="http://www.syby8.com/";

        public  static  final  String BannerURL="apptools/indexad.aspx?";

    }

    public static class Key{

        public  static  final  String V="v";
    }
    public static class  DefaultValue{

        public  static  final  String V="34";
    }


}

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved