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.