recyclerview android android-asynctask android-recyclerview recycler-adapter notifydatasetchanged

android - notifydatasetchanged recyclerview



Endless RecyclerView con Asynctask (1)

Tengo una aplicación que tiene un número ilimitado de recyclerView (cuando se llega a cierta compensación para el final de la lista, llamo al método de interfaz del adaptador recyclerView).
Adaptador RecyclerView

public SearchResultAdapter(ArrayList<String> suggestions) { this.suggestions = suggestions; } public SearchResultAdapter(ArrayList<Word> results, RecyclerView recyclerView) { words = results; this.recyclerView = recyclerView; final LinearLayoutManager mLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (dy > 0) //check for scroll down { visibleItemCount = mLayoutManager.getChildCount(); totalItemCount = mLayoutManager.getItemCount(); pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition(); if (loading) { if ((visibleItemCount + pastVisiblesItems + 14) >= totalItemCount) { if (mOnLoadMoreListener != null) mOnLoadMoreListener.onLoadMore(); loading = false; } } } } }); } public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) { this.mOnLoadMoreListener = mOnLoadMoreListener; } public void setOnSearchResultClickListener(OnSearchResultClickListener mClickListener) { this.mClickListener = mClickListener; } public void setLoading() { loading = true; } @Override public int getItemViewType(int position) { if(words !=null) return words.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM; else return VIEW_TYPE_SUGGESTION; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Context context = parent.getContext(); LayoutInflater inflater = LayoutInflater.from(context); if (suggestions != null) { View view = inflater.inflate(R.layout.activity_suggestion_item, parent, false); return new SuggestionsViewHolder(view); } if (words != null) { // Inflate the custom layout if (viewType == VIEW_TYPE_ITEM) { View view = inflater.inflate(R.layout.activity_main_search_result_item, parent, false); return new WordViewHolder(view); } //inflate loading else if (viewType == VIEW_TYPE_LOADING) { View view = inflater.inflate(R.layout.activity_main_search_result_loading, parent, false); return new LoadingViewHolder(view); } } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { Word word=null; if(words !=null) word = words.get(position); if (viewHolder instanceof LoadingViewHolder) { LoadingViewHolder holder = (LoadingViewHolder) viewHolder; holder.progressBar.setIndeterminate(true); } else if (viewHolder instanceof WordViewHolder) { WordViewHolder holder = (WordViewHolder) viewHolder; holder.wordTextView.setText(word.getTitle()); holder.sourceTextView.setText(word.getSource().getTitle()); } else if (viewHolder instanceof SuggestionsViewHolder){ SuggestionsViewHolder holder = (SuggestionsViewHolder) viewHolder; holder.wordTextView.setText(suggestions.get(position)); } //wordTextView.loadDataWithBaseURL(null,result.toString(), "text/html", "utf-8", null); } @Override public int getItemCount() { return words == null ? (suggestions ==null?0:suggestions.size()) : words.size(); } public static class LoadingViewHolder extends RecyclerView.ViewHolder { public ProgressBar progressBar; public LoadingViewHolder(View itemView) { super(itemView); progressBar = (ProgressBar) itemView.findViewById(R.id.search_item_progressbar); } } public class WordViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { // public TextView titleTextView; private CustomTextView wordTextView; private CustomTextView sourceTextView; private CardView searchResultItem; public WordViewHolder(View itemView) { super(itemView); searchResultItem = (CardView) itemView.findViewById(R.id.search_result_item_cardview); wordTextView = (CustomTextView) itemView.findViewById(R.id.search_result_item_body); sourceTextView = (CustomTextView) itemView.findViewById(R.id.search_result_source); searchResultItem.setOnClickListener(this); } @Override public void onClick(View view) { mClickListener.onSearchResultClick(getAdapterPosition()); } } public class SuggestionsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ // public TextView titleTextView; private CustomTextView wordTextView; private CardView suggestionItem; public SuggestionsViewHolder(View itemView) { super(itemView); suggestionItem = (CardView) itemView.findViewById(R.id.suggestion_item_cardview); wordTextView = (CustomTextView) itemView.findViewById(R.id.activity_suggestion_title); wordTextView.setTypeface(MainActivity.custom_font); suggestionItem.setOnClickListener(this); } @Override public void onClick(View view) { mClickListener.onSuggestionClick(suggestions.get(getAdapterPosition())); } } @Override public int getItemViewType(int position) { if(words !=null) return words.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM; else return VIEW_TYPE_SUGGESTION; }

OnLoadMore

@Override public void onLoadMore() { if (request.getPage() < totalPageAmount) { request.nextPage(); LoadMoreTask task = new LoadMoreTask(request, words, adapter); task.execute(); } }

LoadMoreTask

public LoadMoreTask(Request request, ArrayList<Word> words, SearchResultAdapter adapter){ this.request=request; this.words=words; this.adapter=adapter; this.connection = new Connection(request.getUrl()); } @Override protected void onPreExecute() { super.onPreExecute(); if(words.get(words.size()-1)!=null){ words.add(null); index = words.size() - 1; adapter.notifyItemInserted(index); } } @Override protected Void doInBackground(Void... params) { connection.connect(); String result = connection.getStringFromServer(); Respond respond = new Respond(result); if(!request.isDetailed()) words.addAll(respond.handleSimple()); return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); connection.disconnect(); if(index!=0 && words.get(index)==null){ words.remove(index); adapter.notifyItemRemoved(index+1); } adapter.notifyDataSetChanged(); adapter.setLoading(); }

Como se puede ver, cuando se activa onLoadMore , me conecto al servidor web para obtener más datos y adjuntarlo a la lista de arraylist anterior. La adición de un objeto nulo en preExecute se realiza para cambiar el tipo de viewHolder (Tengo una pequeña viewHolder progressBar carga al final de la lista, y se elimina después de que la asynctask haya finalizado). Este código funciona bastante bien, excepto que notifyDataSetChanged congela la IU un poco. Sí, es lo suficientemente pequeño y se ve solo si se desplaza demasiado rápido, pero de todos modos es molesto. ¿Cómo puedo optimizar este código para eliminar heladas?


notifyItemRangeInserted el problema usando la función notifyItemRangeInserted , parece que esta función necesita menos recursos que notifyDatasetChanged

@Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); connection.disconnect(); adapter.resetLoading(); if(index!=0 && words.get(index)==null){ words.remove(index); adapter.notifyItemRemoved(index); } adapter.notifyItemRangeInserted(index,30); }

Entonces, usar este código todo funciona perfectamente sin nano congelaciones.