Androidプロジェクトのまとめ——Stagg eredGrade LayoutManagerの滝の流れのよくある問題
26801 ワード
背景の紹介:
一つのプロジェクトをする時に、このような要求があります.サーバーにお願いしてから写真を見せてください.美図のような需要があるでしょう.具体的なプロジェクトの詳細は詳しく説明しません.サービス側は国内の優秀なThinkjsフレームに基づいています.クライアント:Android;Androidクライアントの問題についてまとめてみます.後でサービスをまとめます.
デマンド機能ポイントは以下の通りです.1.改ページクエリをサポートし、アップデートしてより多くを検索し、データがある場合は回転圏のローディングがより多く、データがない場合はヒントを与えることを表示します.2.爆布流で表示し、同時に写真の高さがランダムである.
全体の考え方1.oKHttp第三者オープンソースを採用してインターフェースデータ要求を行う;2.RecyclerView+Stagg eredGrade LayoutManagerを使って爆布流のUIを実現する;
よくある問題:1.RecyclerViewはどうやってもっと多くのローディングを実現しますか?2.Stagg eredGridLayoutManagerの表示がもっと多くロードされた時、最後のitemとして単独で画面の幅を満たせず、一つのitemの幅として表示されます.3.Stagg eredGridLayoutManagerはどのようにランダムにitemの高さを設定しますか?4.Stagg eredGridLayoutManagerからデータリフレッシュUIを読み込む際、高度にランダムでページitemのジッタが発生します.5.RecyclerViewの不可解なInconsistency detectedが崩壊する.
埋め立てを開始します.1.recyclerViewはどうやってボトムローディングを実現しますか?まずrecyclerViewスライドイベントをモニターできるようにする. は、recyclerViewが最後のitemにスライドするかどうかを判断する. recyclerViewより多くのRecyclerView.Adapterをロードする設定処理. 関連コード:recyclerViewスライドイベントをモニターし、最後のアイテムにスライドするかどうかを計算します.
主にlayoutManagerの特徴によって、下記の2つの方法を書き換え、layoutManagerに関するSpanの設定方法を呼び出します.
一つのプロジェクトをする時に、このような要求があります.サーバーにお願いしてから写真を見せてください.美図のような需要があるでしょう.具体的なプロジェクトの詳細は詳しく説明しません.サービス側は国内の優秀なThinkjsフレームに基づいています.クライアント:Android;Androidクライアントの問題についてまとめてみます.後でサービスをまとめます.
デマンド機能ポイントは以下の通りです.1.改ページクエリをサポートし、アップデートしてより多くを検索し、データがある場合は回転圏のローディングがより多く、データがない場合はヒントを与えることを表示します.2.爆布流で表示し、同時に写真の高さがランダムである.
全体の考え方1.oKHttp第三者オープンソースを採用してインターフェースデータ要求を行う;2.RecyclerView+Stagg eredGrade LayoutManagerを使って爆布流のUIを実現する;
よくある問題:1.RecyclerViewはどうやってもっと多くのローディングを実現しますか?2.Stagg eredGridLayoutManagerの表示がもっと多くロードされた時、最後のitemとして単独で画面の幅を満たせず、一つのitemの幅として表示されます.3.Stagg eredGridLayoutManagerはどのようにランダムにitemの高さを設定しますか?4.Stagg eredGridLayoutManagerからデータリフレッシュUIを読み込む際、高度にランダムでページitemのジッタが発生します.5.RecyclerViewの不可解なInconsistency detectedが崩壊する.
埋め立てを開始します.1.recyclerViewはどうやってボトムローディングを実現しますか?
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
staggeredGridLayoutManager.invalidateSpanAssignments(); //
currentScrollState = newState;
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
if ((visibleItemCount > 0 && currentScrollState == RecyclerView.SCROLL_STATE_IDLE && (lastVisibleItemPosition) >= totalItemCount - 1)) {
Log.i(TAG, "onScrollStateChanged: ...");
requestMoreData();//
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManagerType == null) {
if (layoutManager instanceof LinearLayoutManager) {
layoutManagerType = LayoutManagerType.LinearLayout;
} else if (layoutManager instanceof GridLayoutManager) {
layoutManagerType = LayoutManagerType.GridLayout;
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
layoutManagerType = LayoutManagerType.StaggeredGridLayout;
} else {
throw new RuntimeException(
"Unsupported LayoutManager used. Valid ones are LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager");
}
}
switch (layoutManagerType) {
case LinearLayout:
lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
break;
case GridLayout:
lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
break;
case StaggeredGridLayout:
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
if (lastPositions == null) {
lastPositions = new int[staggeredGridLayoutManager.getSpanCount()];
}
staggeredGridLayoutManager.findLastVisibleItemPositions(lastPositions);
lastVisibleItemPosition = findMax(lastPositions);
break;
default:
break;
}
}
});
/**
*
*
* @param lastPositions
* @return
*/
private int findMax(int[] lastPositions) {
int max = lastPositions[0];
for (int value : lastPositions) {
if (value > max) {
max = value;
}
}
return max;
}
public static enum LayoutManagerType {
LinearLayout,
StaggeredGridLayout,
GridLayout
}
RecyclerView.Adapterの関連コードは主に2つのView Holderタイプを定義します.TYPE_BOTTOMは底のview Holder、TYPE_を表します.NOMALは正常なitemのview Holderと表し、positionによって異なるview holderを表示します.コードの中には上のStaggreed LayoutManagerに対する問題処理もあります.具体的には以下に詳しく説明します.public class XXXRcyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_BOTTOM = 0;
private static final int TYPE_NOMAL = 1;
private LayoutInflater inflater;
private Context mContext;
private int preNumb = 0;
private boolean isLoading = false;
************
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_BOTTOM){
return new BottomViewHolder(inflater.inflate(R.layout.item_type_bottom,parent,false));
}
return new NomalViewHolder(inflater.inflate(R.layout.item_qr_code_say_rcy,parent,false));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof NomalViewHolder){
NomalViewHolder nomalViewHolder = (NomalViewHolder) holder;
********* ***********
ViewGroup.LayoutParams lp = nomalViewHolder.imgView.getLayoutParams();
int scale = new Random().nextInt(10);
if (scale < 5){
scale = 9;
}
lp.height= (int) (UIUtil.dp2px(mContext,200) *0.1 * scale);
lp.width= RecyclerView.LayoutParams.MATCH_PARENT;
nomalViewHolder.imgView.setLayoutParams(lp);
********* Imageview *********
}else if (holder instanceof BottomViewHolder){
BottomViewHolder bottomViewHolder = (BottomViewHolder) holder;
if (isLoading){
bottomViewHolder.bottomContainer.setVisibility(View.VISIBLE);
bottomViewHolder.imgView.setVisibility(View.VISIBLE);
bottomViewHolder.textView.setVisibility(View.VISIBLE);
/*** ***/
}else{
bottomViewHolder.bottomContainer.setVisibility(View.VISIBLE);
bottomViewHolder.imgView.setVisibility(View.GONE);
bottomViewHolder.textView.setVisibility(View.VISIBLE);
/*** ***/
}
}
}
@Override
public int getItemCount() {
return xxxxList.size() + 1;
}
/**
* viewType
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
if (position < qrCodeSayBeanList.size()){
return TYPE_NOMAL;
}
return TYPE_BOTTOM;
}
/**
* GridLayoutManager , item
* @param recyclerView
*/
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return isFooter(position) ? gridManager.getSpanCount() : 1;
}
});
}
}
/**
* StaggeredGridLayoutManager , item
* @param holder
*/
@Override
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
super.onViewAttachedToWindow(holder);
if (isStaggeredGridLayout(holder)) {
handleLayoutIfStaggeredGridLayout(holder, holder.getLayoutPosition());
}
}
private boolean isStaggeredGridLayout(RecyclerView.ViewHolder holder) {
ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
if (layoutParams != null && layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
return true;
}
return false;
}
protected void handleLayoutIfStaggeredGridLayout(RecyclerView.ViewHolder holder, int position) {
if ( isFooter(position)){
StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
p.setFullSpan(true);
}
}
/**
*
* @param position
* @return
*/
private boolean isFooter(int position) {
if (position == qrCodeSayBeanList.size()){
return true;
}
return false;
}
/**
* viewHolder
*/
private static class BottomViewHolder extends RecyclerView.ViewHolder{
private View bottomContainer;
private ImageView imgView;
private TextView textView;
public BottomViewHolder(View itemView) {
super(itemView);
bottomContainer = itemView.findViewById(R.id.bottom_container);
imgView = itemView.findViewById(R.id.img_loading);
textView = itemView.findViewById(R.id.txt_tips);
}
}
/**
* viewHolder
*/
private static class NomalViewHolder extends RecyclerView.ViewHolder{
private ImageView imgView;
private TextView txtViewNumb;
private TextView txtLikedNumb;
public NomalViewHolder(View itemView) {
super(itemView);
imgView = itemView.findViewById(R.id.img_view);
txtViewNumb = itemView.findViewById(R.id.txt_view_numbs);
txtLikedNumb = itemView.findViewById(R.id.txt_tap_liked_numbs);
}
}
/**
* ,
*/
public void startLoading(){
isLoading = true;
// notifyDataSetChanged();
notifyItemRangeChanged(preNumb,qrCodeSayBeanList.size());// item , ,
preNumb = xxxList.size();
}
/**
* ,
*/
public void stopLoading(){
isLoading = false;
// notifyDataSetChanged();
notifyItemRangeChanged(preNumb,qrCodeSayBeanList.size());// item , ,
preNumb = xxxList.size();
}
/**
* ,
*/
public void stopLoadingNotifyAll(){
isLoading = false;
notifyDataSetChanged();
}
}
2.Stagg eredGridLayoutManagerの表示がもっと多くロードされた時、最後のitemとして単独で画面の幅を満たせず、一つのitemの幅として表示されます.主にlayoutManagerの特徴によって、下記の2つの方法を書き換え、layoutManagerに関するSpanの設定方法を呼び出します.
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return isFooter(position) ? gridManager.getSpanCount() : 1;
}
});
StaggeredGridLayoutManager.LayoutParams.setFullSpan(true);
/**
* GridLayoutManager , item
* @param recyclerView
*/
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return isFooter(position) ? gridManager.getSpanCount() : 1;
}
});
}
}
/**
* StaggeredGridLayoutManager , item
* @param holder
*/
@Override
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
super.onViewAttachedToWindow(holder);
if (isStaggeredGridLayout(holder)) {
handleLayoutIfStaggeredGridLayout(holder, holder.getLayoutPosition());
}
}
private boolean isStaggeredGridLayout(RecyclerView.ViewHolder holder) {
ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
if (layoutParams != null && layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
return true;
}
return false;
}
protected void handleLayoutIfStaggeredGridLayout(RecyclerView.ViewHolder holder, int position) {
if ( isFooter(position)){
StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
p.setFullSpan(true);
}
}
/**
*
* @param position
* @return
*/
private boolean isFooter(int position) {
if (position == qrCodeSayBeanList.size()){
return true;
}
return false;
}
3.Stagg eredGridLayoutManagerはどのようにランダムにitemの高さを設定しますか? ViewGroup.LayoutParams lp = nomalViewHolder.imgView.getLayoutParams();
int scale = new Random().nextInt(10);
if (scale < 5){
scale = 9;
}
lp.height= (int) (UIUtil.dp2px(mContext,200) *0.1 * scale);
lp.width= RecyclerView.LayoutParams.MATCH_PARENT;
nomalViewHolder.imgView.setLayoutParams(lp);
4.Stagg eredGridLayoutManagerからデータリフレッシュUIを読み込む際、高度にランダムでページitemのジッタが発生します.ここでは直接notifyData SetChangedを呼び出します.これは全体の更新で、更新時にitemの高さがランダムに割り当てられ、データが更新された時にジッタが発生します.notifyItemRangeChangedを採用してローカルリフレッシュすることを提案します. /**
* ,
*/
public void startLoading(){
isLoading = true;
// notifyDataSetChanged();
notifyItemRangeChanged(preNumb,qrCodeSayBeanList.size());// item , ,
preNumb = qrCodeSayBeanList.size();
}
/**
* ,
*/
public void stopLoading(){
isLoading = false;
// notifyDataSetChanged();
notifyItemRangeChanged(preNumb,xxxList.size());// item , ,
preNumb = xxxList.size();
}
/**
* ,
*/
public void stopLoadingNotifyAll(){
isLoading = false;
notifyDataSetChanged();
}
5.RecyclerViewの不可解なInconsistency detectedが崩壊する.CustoomStagg eredGrade LayoutManagerをカスタマイズしてオンラyoutChildrenで異常を捕獲します.public class CustomStaggeredGridLayoutManager extends StaggeredGridLayoutManager {
private static final String TAG = "LOG_CustomStaggered";
public CustomStaggeredGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public CustomStaggeredGridLayoutManager(int spanCount, int orientation) {
super(spanCount, orientation);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
try {
super.onLayoutChildren(recycler, state);
}catch (Exception e){
Log.i(TAG, "onLayoutChildren: e " + e.getMessage());
}
}
}
参照https://www.jianshu.com/p/2eca433869e9