項(xiàng)目地址
https://github.com/codeestX/GeekNews
值得借鑒的地方
- 項(xiàng)目結(jié)構(gòu)(MVP+Dagger2)
- Retrofit對多個(gè)baseUrl的管理
- realm的使用
- 側(cè)邊欄導(dǎo)航、tab導(dǎo)航的使用
- 單Activity+多Fragment的管理(基于me.yokeyword:fragmentation)
- 頁面跳轉(zhuǎn)共享資源的使用(列表->詳情共享新聞圖片)
- ==搜索框的使用,搜索時(shí)間的發(fā)布訂閱處理邏輯==
- Logger的使用,見LogUtil
- 在Application中調(diào)用InitializeService,初始化了Logger,Bugly(錯(cuò)誤收集+統(tǒng)計(jì)),LeakCanary(內(nèi)存泄漏檢測),BlockCanary(UI阻塞監(jiān)控),tbs webview(騰訊webview服務(wù))
解讀
- RxBus事件總線
DailyPresenter的構(gòu)造方法中有一個(gè)registerEvent方法
@Inject
public DailyPresenter(RetrofitHelper mRetrofitHelper,RealmHelper mRealHelper) {
this.mRetrofitHelper = mRetrofitHelper;
this.mRealmHelper = mRealHelper;
registerEvent();
}
registerEvent()是訂閱RxBus事件的
private void registerEvent() {
Subscription rxSubscription = RxBus.getDefault().toObservable(CalendarDay.class)
.subscribeOn(Schedulers.io())
.map(new Func1<CalendarDay, String>() {
...
在DailyFragment中,發(fā)布RxBus事件
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
if(currentDate.equals(DateUtil.getTomorrowDate())) {
mPresenter.getDailyData();
} else {
int year = Integer.valueOf(currentDate.substring(0,4));
int month = Integer.valueOf(currentDate.substring(4,6));
int day = Integer.valueOf(currentDate.substring(6,8));
CalendarDay date = CalendarDay.from(year, month - 1, day);
RxBus.getDefault().post(date);
}
}
});
- DailyAdapter
有三種樣式:圖片滾動(dòng)欄(類似于web的banner)、日期、新聞item
@Override
public int getItemViewType(int position) {
if(!isBefore) {
if(position == 0) {
return ITEM_TYPE.ITEM_TOP.ordinal();
} else if(position == 1) {
return ITEM_TYPE.ITEM_DATE.ordinal();
} else {
return ITEM_TYPE.ITEM_CONTENT.ordinal();
}
} else {
if(position == 0) {
return ITEM_TYPE.ITEM_DATE.ordinal();
} else {
return ITEM_TYPE.ITEM_CONTENT.ordinal();
}
}
}
其中positi==0的就是圖片滾動(dòng)欄,由一個(gè)ViewPager實(shí)現(xiàn),該ViewPager的Adapter是由另外一個(gè)Adapter持有的
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == ITEM_TYPE.ITEM_TOP.ordinal()) {
mAdapter = new TopPagerAdapter(mContext,mTopList);
return new TopViewHolder(inflater.inflate(R.layout.item_top, parent, false));
} else if(viewType == ITEM_TYPE.ITEM_DATE.ordinal()) {
return new DateViewHolder(inflater.inflate(R.layout.item_date, parent, false));
}
return new ContentViewHolder(inflater.inflate(R.layout.item_daily, parent, false));
}
- compose的使用
可以少寫切換線程的代碼
@Override
public void getDailyData() {
Subscription rxSubscription = mRetrofitHelper.fetchDailyListInfo()
.compose(RxUtil.<DailyListBean>rxSchedulerHelper())
...
}
其中的compose主要是在io線程處理數(shù)據(jù),ui線程處理結(jié)果
/**
* 統(tǒng)一線程處理
* @param <T>
* @return
*/
public static <T> Observable.Transformer<T, T> rxSchedulerHelper() { //compose簡化線程
return new Observable.Transformer<T, T>() {
@Override
public Observable<T> call(Observable<T> observable) {
return observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}
- 新聞的item點(diǎn)擊進(jìn)入detail時(shí)會(huì)共享新聞圖片
xml如下
<com.codeest.geeknews.widget.SquareImageView
android:id="@+id/iv_daily_item_image"
android:transitionName="shareView"
android:src="@mipmap/ic_launcher"
android:layout_width="@dimen/list_image_size"
android:layout_height="@dimen/list_image_size" />
...
java如下
mAdapter.setOnItemClickListener(new DailyAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position,View shareView) {
mPresenter.insertReadToDB(mList.get(position).getId());
mAdapter.setReadState(position,true);
if(mAdapter.getIsBefore()) {
mAdapter.notifyItemChanged(position + 1);
} else {
mAdapter.notifyItemChanged(position + 2);
}
Intent intent = new Intent();
intent.setClass(mContext, ZhihuDetailActivity.class);
intent.putExtra("id",mList.get(position).getId());
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(mActivity, shareView, "shareView");
mContext.startActivity(intent,options.toBundle());
}
});
detail中做如下處理
xml如下
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:transitionName="shareView"
android:fitsSystemWindows="true">
...
java如下
(getWindow().getSharedElementEnterTransition()).addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
}
@Override
public void onTransitionEnd(Transition transition) {
/**
* 測試發(fā)現(xiàn)部分手機(jī)(如紅米note2)上加載圖片會(huì)變形,沒有達(dá)到centerCrop效果
* 查閱資料發(fā)現(xiàn)Glide配合SharedElementTransition是有坑的,需要在Transition動(dòng)畫結(jié)束后再加載圖片
* https://github.com/TWiStErRob/glide-support/blob/master/src/glide3/java/com/bumptech/glide/supportapp/github/_847_shared_transition/DetailFragment.java
*/
isTransitionEnd = true;
if (imgUrl != null) {
isImageShow = true;
ImageLoader.load(mContext, imgUrl, detailBarImage);
}
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});