看完此文章 你就會(huì)學(xué)到什么...
- RecyclerView添加頭部,尾部,或list列表中某位置添加view
- RecyclerView+SwipeRefreshLayout 實(shí)現(xiàn)上下拉刷新效果
- 分頁加載數(shù)據(jù)
- 列表優(yōu)化方案
- 利用Glide加載圖片擂送,滑動(dòng)的時(shí)候按back鍵啊胶,App會(huì)crash蹦掉處理炮捧。
添加依賴
//recyclerview
compile 'com.android.support:recyclerview-v7:25.1.1'
//glide
compile 'com.github.bumptech.glide:glide:3.7.0'
//butterknife 注意需要在三個(gè)第三添加代碼
//1 module gradle里面底部添加
compile 'com.jakewharton:butterknife:8.5.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
//2 module gradle 里面頂部添加
apply plugin: 'com.jakewharton.butterknife'
//3 在project gradle里面添加
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.jakewharton:butterknife-gradle-plugin:8.5.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
RecyclerView 任意位置添加view
RecyclerView中有以下三個(gè)函數(shù):
getItemCount --得到列表中Item的總個(gè)數(shù)
getItemViewType(int position)--決定布局使用哪一種類型,返回一個(gè)int型標(biāo)志position唬血,傳遞給onCreateViewHolder的第二個(gè)參數(shù)。
通俗說:一個(gè)列表有很多個(gè)Item唤崭,每個(gè)Item都可以是自己的一個(gè)自定義的布局且每個(gè)都會(huì)有一個(gè)唯一的位置拷恨,可以通過Item中的位置position標(biāo)志,規(guī)定這個(gè)position將會(huì)返回的Item的布局類型谢肾。例如:
@Override
public int getItemViewType(int position) {
if (position == 0) {
return TYPE_HEAD;
} else if (position + 1 == getItemCount()) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
3.onCreateViewHolder(ViewGroup parent, int viewType) 依據(jù)getItemViewType返回的每個(gè)position位置所返回的布局類型腕侄,去渲染具體的ViewHolder 。例如:
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HEAD) {
View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_discover_head, parent, false);
return new HeadViewHolder(view);
} else if (viewType == TYPE_ITEM) {
View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_discover_base, parent, false);
return new ItemViewHolder(view);
} else if (viewType == TYPE_FOOTER) {
View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_discover_foot, parent, false);
return new FootViewHolder(view);
}
return null;
}
RecyclerView+SwipeRefreshLayout 實(shí)現(xiàn)上下拉刷新效果
xml如下布局
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/discover_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
</android.support.v4.widget.SwipeRefreshLayout>
用法
//進(jìn)入界面時(shí)候顯示動(dòng)畫
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
}
});
//每次下拉刷新時(shí)候加載刷新數(shù)據(jù)
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
if (!isLoading) {
isLoading = true;
data.clear();
getData();
}
}
});
利用了SwipeRefreshLayout實(shí)現(xiàn)了下拉數(shù)據(jù)刷新功能芦疏,而上拉加載數(shù)據(jù)是利用RecyclerView的
public abstract static class OnScrollListener {
//newState 參數(shù)有:
// SCROLL_STATE_TOUCH_SCROLL(1) 正在滾動(dòng)
// SCROLL_STATE_FLING(2) 手指做了拋的動(dòng)作(手指離開屏幕前冕杠,用力滑了一下)
// SCROLL_STATE_IDLE(0) 停止?jié)L動(dòng)
public void onScrollStateChanged(RecyclerView recyclerView, int newState){}
//滾動(dòng)時(shí)一直回調(diào),直到停止?jié)L動(dòng)時(shí)才停止回調(diào)酸茴。單擊時(shí)回調(diào)一次
public void onScrolled(RecyclerView recyclerView, int dx, int dy){}
}
分頁加載數(shù)據(jù)&&列表優(yōu)化方案(思想編程)
分頁加載:
實(shí)際就是每次上拉分预,然后將數(shù)據(jù)加進(jìn)list集合里面,而獲取特定數(shù)據(jù)的控制薪捍,就是從頁碼來笼痹,每次上拉都將page頁碼加一放到請求參數(shù)里面配喳,而每次下拉,將list集合的數(shù)據(jù)清除凳干,將page還原成原來的1晴裹,請求到的數(shù)據(jù)放進(jìn)list里面。
列表優(yōu)化方案:
1.布局方面纺座,盡量少點(diǎn)組件嵌套息拜,盡量多用LinearLayout,少用RelativeLayout之類的净响,因?yàn)镽elativeLayout渲染時(shí)候需要需要資源較多少欺。
2.圖片優(yōu)化,建議使用現(xiàn)有的圖片框架馋贤,例如 Glide赞别,Picasso,F(xiàn)resco配乓,ImageLoader 等的開源框架仿滔,因?yàn)槔锩婧芎玫姆庋b了圖片緩存機(jī)制,以及沒用時(shí)候犹芹,或者用頻率少的時(shí)候崎页,那圖片緩存會(huì)優(yōu)先被回收。
3.圖片加載. 當(dāng)列表滑動(dòng)時(shí)候腰埂,將圖片用占位圖片顯示飒焦,或則圖片完全不顯示來處理,等滑動(dòng)停止后屿笼,再加載牺荠。本demo用Glide,結(jié)合RecyclerView.OnScrollListener 來處理圖片加載的驴一。具體看demo源碼休雌。
4.每次分頁加載數(shù)據(jù),數(shù)據(jù)添加進(jìn)List的時(shí)間(也可以說是網(wǎng)絡(luò)請求數(shù)據(jù)的時(shí)間最好在什么時(shí)候)肝断,經(jīng)過本人研究了bilibili安卓App和其它App列表滑動(dòng)流暢度的對(duì)比杈曲,bilibili是滑動(dòng)最不卡最流暢的,為什么這樣呢胸懈?實(shí)際上是因?yàn)榉猪摃r(shí)網(wǎng)絡(luò)請求數(shù)據(jù)的開始時(shí)間決定的鱼蝉。在RecyclerView.OnScrollListener 的onScrolled滑動(dòng)事件中處理。
下面代碼中有個(gè) 5 箫荡,它就是代碼的滑動(dòng)流暢的關(guān)鍵魁亦,也可以不一定是5,按實(shí)際需要寫羔挡。
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
if (lastVisibleItemPosition + 5 >= adapter.getItemCount()) {
boolean isRefreshing = swipeRefreshLayout.isRefreshing();
if (isRefreshing) {
adapter.notifyItemRemoved(adapter.getItemCount());
return;
}
if (!isLoading) {
isLoading = true;
getData();
}
}
}
這樣的優(yōu)化優(yōu)點(diǎn):滑動(dòng)特別流暢 缺點(diǎn):可能因?yàn)槠聊坏拇笮〔灰欢虞d開始時(shí)間不同洁奈,還有的就是你體驗(yàn)不到上拉加載數(shù)據(jù)的動(dòng)畫感(上拉加載更多.. 這樣的字你就難看到了间唉,不過網(wǎng)絡(luò)慢的時(shí)候,還是可以看到的)~利术。
利用Glide加載圖片呈野,滑動(dòng)的時(shí)候按back鍵,App會(huì)crash蹦掉處理印叁。
剛所說的列表滑動(dòng)優(yōu)化處理被冒,而我自己就隨便用了個(gè)Glide去加載圖片,可以看到轮蜕,在一瞬間滑動(dòng)昨悼,然后我按back鍵退出的時(shí)候,App會(huì)crash蹦掉跃洛,why率触?why?why汇竭?why葱蝗? due to “You cannot start a load for a destroyed activity”。
原因的出處是因?yàn)槲以诨瑒?dòng)那里做的圖片滑動(dòng)時(shí)停止加載细燎,停止時(shí)加載圖片導(dǎo)致的,“You cannot start a load for a destroyed activity”,說白了就是activity在你按back鍵時(shí)候已經(jīng)銷毀了两曼,而那個(gè)滾動(dòng)事件的Glide圖片處理事件還在執(zhí)行。
mOnScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case SCROLL_STATE_IDLE:
Glide.with(MainActivity.this).resumeRequests();
break;
case SCROLL_STATE_DRAGGING:
case SCROLL_STATE_SETTLING:
Glide.with(MainActivity.this).pauseRequests();
break;
}
}
解決問題:
- 嘗試在每個(gè)Glide使用前判斷玻驻,而且在activity的onDestory方法里寫上如下悼凑,解決問題失敗击狮! 博客鏈接:http://blog.csdn.net/a940659387/article/details/50555327
if(Util.isOnMainThread()) {
Glide.with(this).pauseRequest();
}
- 嘗試在每個(gè)Glide使用時(shí)候佛析,this改成getApplicationContext()益老,依然crash彪蓬! 博客鏈接:http://www.reibang.com/p/4a3177b57949
Glide.with(this).resumeRequests();
- 我使用的推薦成功可以完美oknice的方法,不在Glide那里下手捺萌,在滾動(dòng)那里下手档冬。 Get something: 思維轉(zhuǎn)變,別一直糾纏Glide那里桃纯。
@Override
protected void onPause() {
recyclerView.removeOnScrollListener(mOnScrollListener);
super.onPause();
}
僅供學(xué)習(xí)使用 提供思路酷誓,具體實(shí)現(xiàn)還是得按照自己業(yè)務(wù)邏輯處理
源碼地址
https://github.com/androidHRTZ/SuperRecyclerView.git
轉(zhuǎn)載請?jiān)陂_頭注明作者詳細(xì)信息和本文出處 謝謝