UGank项目的理解分析

通过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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值