es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo cambiar el texto de TextView dentro de los elementos de RecyclerView sin utilizar notifyItemChanged?

Tengo un recyclerView que muestra un título y una vista previa del enlace en cada elemento. Quiero buscar texto en el título y resaltar el texto buscado si el título contiene el texto.
El problema es: cuando busco algo, todo funciona como se espera, pero la vista previa del enlace vuelve a comenzar y tarda unos segundos en cargar la vista previa de nuevo.
¿Existe alguna forma de evitar volver a cargar/reiniciar la vista previa del enlace? o
¿Existe alguna forma de notificar solo un textView dentro del elemento y mantener las otras cosas como estaban?

Código para la búsqueda:

public boolean performSearch(TextView textViewResult, String searchKey){
    this.searchKey = searchKey;

    searchedPosition.clear();
    for(int i=0; i<links.size(); i++){
        if(links.get(i).getTitle().toLowerCase().contains(searchKey)) {
            searchedPosition.add(i);
        }
    }

    if(searchedPosition.size()==0)
        return false;//for downArrow
    else {
        currentPosition = 0;

        for(int i=0; i<searchedPosition.size(); i++)
            notifyItemChanged(searchedPosition.get(i));

        scrollListener.scrollToPosition(searchedPosition.get(currentPosition));

        return true;
    }
}

onBindViewholder:

@Override
public void onBindViewHolder(@NonNull final FileLayoutHolder2 holder, final int position) {

    if(searchKey!=null && links.get(position).getTitle().toLowerCase().contains(searchKey)){
        String newString = links.get(position).getTitle().replaceAll(
                "(?i)"+ Pattern.quote(searchKey),
                "<font color='red'>"+searchKey+"</font>");
        holder.textViewHeading.setText(Html.fromHtml(newString));
    }
    else{
        holder.textViewHeading.setText(links.get(position).getTitle());
    }

    try {//code for showing link preview: asynctask
     }
    catch(Exception ignored){}

}
Tags:  ,

Answer

  1. Avatar for davy.ai

    Una forma de evitar que la vista previa del enlace se recargue o reinicie podría ser utilizar un mecanismo de almacenamiento en caché donde los datos de la vista previa del enlace se almacenen localmente y se recuperen desde allí en lugar de volver a solicitarlos al servidor. Esto requeriría una implementación adicional para manejar la caché y la expiración de la caché, pero resultaría en una experiencia más fluida para el usuario.

    En cuanto a notificar solo un textView dentro del elemento, puedes usar el método notifyItemChanged(int position, Object payload) en lugar del método notifyItemChanged(int position). Esto te permite pasar un objeto de carga útil y actualizar solo las vistas relevantes en lugar de actualizar todo el elemento. En tu caso, puedes pasar un objeto de carga útil que contenga la clave de búsqueda y actualizar solo el textViewHeading en consecuencia, manteniendo la vista previa del enlace tal como está. Aquí tienes un ejemplo:

    public class SearchResultPayload {
        private String searchKey;
    
        public SearchResultPayload(String searchKey) {
            this.searchKey = searchKey;
        }
    
        public String getSearchKey() {
            return searchKey;
        }
    }
    
    // Dentro del método performSearch
    for (int i = 0; i < searchedPosition.size(); i++) {
        SearchResultPayload payload = new SearchResultPayload(searchKey);
        notifyItemChanged(searchedPosition.get(i), payload);
    }
    
    // Dentro del método onBindViewHolder
    @Override
    public void onBindViewHolder(@NonNull final FileLayoutHolder2 holder, final int position, @NonNull List<object> payloads) {
        if (!payloads.isEmpty()) {
            SearchResultPayload payload = (SearchResultPayload) payloads.get(0);
            String searchKey = payload.getSearchKey();
    
            if (links.get(position).getTitle().toLowerCase().contains(searchKey)) {
                String newString = links.get(position).getTitle().replaceAll(
                    "(?i)" + Pattern.quote(searchKey),
                    "<font color='red'>" + searchKey + "</font>");
                holder.textViewHeading.setText(Html.fromHtml(newString));
            }
        } else {
            holder.textViewHeading.setText(links.get(position).getTitle());
        }
    
        try {
            // código para mostrar la vista previa del enlace: tarea asíncrona
        } catch (Exception ignored) {}
    }
    

    En el código anterior, se utiliza el método notifyItemChanged(int position, Object payload) para pasar un objeto SearchResultPayload con la clave de búsqueda y actualizar solo el textViewHeading al realizar la búsqueda. En el método onBindViewHolder, se verifica la lista payloads para ver si hay alguna carga útil y, si la hay, se recupera la clave de búsqueda y se actualiza el textViewHeading en consecuencia. De lo contrario, se actualiza el textViewHeading con el título original. De esta manera, la vista previa del enlace no se ve afectada durante la búsqueda.

Comments are closed.