UGank项目的理解分析

来源:互联网 发布:照片大小修剪软件 编辑:程序博客网 时间:2024/06/05 11:58

通过Github开源项目学习知识,是一种非常好的学习方式。下面我们就来看看一个非常流行的框架App,它采用了最火的OkHttp+Rxjava+Retrofit来搭建网络框架,并且完全遵守Metarial design 新特性,还有项目采用了MVP模式,是真正的学习干货,在此声明,博客只是个人学习记录的方式。
UGank下载地址

/**业务操作父类,定义两个基本的操作*/public interface BasePresenter {    void subscribe();    void unsubscribe();}/**定义一个类,里面有两个接口,一个涉及界面操作,一个涉及业务操作**/public class LauncherContract {    interface View extends BaseView {        void goHomeActivity();        void loadImg(String url);    }    interface Presenter extends BasePresenter {    }}

定义一个业务实现类,来实现业务接口。

/** * LauncherPresenter * Presenter的具体实现类 */public class LauncherPresenter implements LauncherContract.Presenter {    /**     *这是一个接口,用来操作UI     */    private LauncherContract.View mLauncherView;    /**     * 通过构造传递接口对象     * @param view     */    public LauncherPresenter(LauncherContract.View view) {        mLauncherView = view;    }    /**     * 操作业务逻辑     */    @Override    public void subscribe() {       if (!ConfigManage.INSTANCE.isShowLauncherImg()) {            mLauncherView.goHomeActivity();            return;        }        String imgCacheUrl = ConfigManage.INSTANCE.getBannerURL();        if (!TextUtils.isEmpty(imgCacheUrl)) {            mLauncherView.loadImg(imgCacheUrl);        } else {            mLauncherView.goHomeActivity();        }    }    /**     * Activity销毁时的业务操作     */    @Override    public void unsubscribe() {    }}

然后界面Activity实现业务接口的Ui操作接口,并且持有一个业务操作接口实现类对象。

/** * LauncherActivity * SplashActivity实现了Ui操作接口 */public class LauncherActivity extends AppCompatActivity implements LauncherContract.View {    @BindView(R.id.img_launcher_welcome)    AppCompatImageView mImageView;    // 记录该 Activity 是否在前台显示    private boolean isResume;    /**     * 创建了一个业务操作的对象,通过传参把界面对象传入     */    private LauncherContract.Presenter mLauncherPresenter = new LauncherPresenter(this);    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);        setContentView(R.layout.activity_launcher);        ButterKnife.bind(this);//绑定View对象        mLauncherPresenter.subscribe();//执行业务操作    }    /**     * UI界面操作,加载显示Logo妹子     * @param url     */    @Override    public void loadImg(String url) {        try {            Picasso.with(this).load(url).into(mImageView, new Callback() {                        @Override                        public void onSuccess() {                            Handler handler = new Handler();                            handler.postDelayed(new Runnable() {                                @Override                                public void run() {                                    if (!isResume) {                                        finish();                                        return;                                    }                                   goHomeActivity();                                }                            }, 1200);                        }                        @Override                        public void onError() {                            goHomeActivity();                        }                    });        } catch (Exception e) {            goHomeActivity();        }    }    @Override    protected void onResume() {        super.onResume();        isResume = true;    }    @Override    protected void onPause() {        super.onPause();        isResume = false;    }    @Override    public void goHomeActivity() {        Intent intent = new Intent(LauncherActivity.this, HomeActivity.class);        startActivity(intent);        // Activity 切换淡入淡出动画        overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);        finish();    }    @Override    public void onBackPressed() {        // 禁掉返回键    }    /**     * Activity销毁时的业务逻辑     */    @Override    protected void onDestroy() {        super.onDestroy();        mLauncherPresenter.unsubscribe();    }}

通过实现接口的形式,来分离UI和业务之间的耦合,然后在Presenter层来反操作Ui,去实现业务。
然后我们看看网络框架工具类。

/** * 网络层 * 封装OkHttp和Retrofit+RxJava搭建网络框架 */public class NetWork {    private static GankApi gankApi; //使用Retrofit封装请求    private static OkHttpClient okHttpClient = new OkHttpClient();// 创建OkHttpClient实例    //使用Gson解析的解析工厂类,来自Retrofit包    private static Converter.Factory gsonConverterFactory =    GsonConverterFactory.create();    //使用RxJava来创建观察者对象的工厂类,来自Retrofit包    private static CallAdapter.Factory rxJavaCallAdapterFactory = RxJavaCallAdapterFactory.create();    public static GankApi getGankApi() {        if (gankApi == null) {            Retrofit retrofit = new Retrofit.Builder().client(okHttpClient)                    .baseUrl("http://gank.io/api/")                    .addConverterFactory(gsonConverterFactory)                    .addCallAdapterFactory(rxJavaCallAdapterFactory)                    .build();            gankApi = retrofit.create(GankApi.class);        }        return gankApi;    }}/** * gank.io 接口 * 使用注解来定义网络接口和需要的传参,和Model层实现链接 */public interface GankApi {   /**    android、ios、前端等数据接口   */    @GET("data/{category}/{number}/{page}")    Observable<CategoryResult> getCategoryDate(@Path("category") String category,          @Path("number") int number, @Path("page") int page);    /**    *首页Banner的妹子图接口    */    @GET("random/data/福利/{number}")    Observable<CategoryResult> getRandomBeauties(@Path("number") int number);    /**    搜索框接口    */    @GET("search/query/{key}/category/all/count/{count}/page/{page}")    Observable<SearchResult> getSearchResult(@Path("key") String key,     @Path("count") int count, @Path("page") int page);}

项目总共三个接口,妹子图通过FloatingActionButton来获取下一张,底部的Fragement数据通过传参的不同,返回不同的数据集合进行展示,还有一个查询接口来查询数据。下面看看最主要的数据获取的Presenter。

/** * CategoryPresenter * 首页所有的Fragment的数据,通过 View层的(mCategoryView.getCategoryName()来改变数据展示 */public class CategoryPresenter implements CategoryContract.Presenter {    private int mPage = 1;//数据的页数    private CategoryContract.View mCategoryView;//View层的对象引用    @NonNull    private CompositeSubscription mSubscriptions;//统一的事件回调监听器    public CategoryPresenter(CategoryContract.View androidView) {        mCategoryView = androidView;        mSubscriptions = new CompositeSubscription(); //创建统一的事件回调监听器    }    /**     * 加载数据     */    @Override    public void subscribe() {        getCategoryItems(true);    }    /**     * 清空订阅器     */    @Override    public void unsubscribe() {        mSubscriptions.clear();    }    @Override    public void getCategoryItems(final boolean isRefresh) {        if (isRefresh) {            mCategoryView.showSwipeLoading();            mPage = 1;        } else {            mPage += 1;        }        Subscription subscription = NetWork.getGankApi()                .getCategoryDate(mCategoryView.getCategoryName(), GlobalConfig.PAGE_SIZE_CATEGORY, mPage)                .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())                .subscribe(new Observer<CategoryResult>() {                    @Override                    public void onCompleted() {                    }                    @Override                    public void onError(Throwable e) {                        mCategoryView.hideSwipeLoading(); //隐藏加载框                      mCategoryView.getCategoryItemsFail(mCategoryView.getCategoryName()                        + " 列表数据获取失败。");                    }                    @Override                    public void onNext(CategoryResult androidResult) {                        if (isRefresh) {//是否刷新                            mCategoryView.setCategoryItems(androidResult);                            mCategoryView.hideSwipeLoading();                            mCategoryView.setLoading();                        } else {                            mCategoryView.addCategoryItems(androidResult); //添加数据                        }                    }                });        mSubscriptions.add(subscription);//添加订阅    }}

可以看出,网络数据获取发生在Presenter层,然后通过拿到View层的一个引用去操作UI展示,每一个业务或者Ui的更改,都会对应一个接口定义的一个抽象方法,然后通过实现的方式去实现业务逻辑。

FloatingActionButton 完全解析
Material Design之CoordinatorLayout+AppBarLayout实现上滑隐藏ToolBar

0 0
原创粉丝点击