Estoy recibiendo datos desde el servidor y, a continuación, analizar y almacenar en una Lista. Yo estoy usando esta lista para el RecyclerView del adaptador. Estoy utilizando Fragmentos.

Estoy usando un Nexus 5 con KitKat. Estoy usando la biblioteca de soporte para este. Será esto una diferencia?

Aquí está mi código: (utilice los datos de prueba para la pregunta)

Variables Miembro:

List<Business> mBusinesses = new ArrayList<Business>();

RecyclerView recyclerView;
RecyclerView.LayoutManager mLayoutManager;
BusinessAdapter mBusinessAdapter;

Mi onCreateView():

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    //Getting data from server
    getBusinessesDataFromServer();

    View view = inflater.inflate(R.layout.fragment_business_list,
            container, false);
    recyclerView = (RecyclerView) view
            .findViewById(R.id.business_recycler_view);
    recyclerView.setHasFixedSize(true);

    mLayoutManager = new LinearLayoutManager(getActivity());
    recyclerView.setLayoutManager(mLayoutManager);

    mBusinessAdapter = new BusinessAdapter(mBusinesses);
    recyclerView.setAdapter(mBusinessAdapter);

    return view;
}

Después de recibir los datos desde el servidor, parseResponse() se llama.

protected void parseResponse(JSONArray response, String url) {
    //insert dummy data for demo

    mBusinesses.clear();

    Business business;

    business = new Business();
    business.setName("Google");
    business.setDescription("Google HeadQuaters");
    mBusinesses.add(business);

    business = new Business();
    business.setName("Yahoo");
    business.setDescription("Yahoo HeadQuaters");
    mBusinesses.add(business);

    business = new Business();
    business.setName("Microsoft");
    business.setDescription("Microsoft HeadQuaters");
    mBusinesses.add(business);

    Log.d(Const.DEBUG, "Dummy Data Inserted\nBusinesses Length: "
            + mBusinesses.size());

    mBusinessAdapter = new BusinessAdapter(mBusinesses);
    mBusinessAdapter.notifyDataSetChanged();
}

Mi BusinessAdapter:

public class BusinessAdapter extends
RecyclerView.Adapter<BusinessAdapter.ViewHolder> {
private List<Business> mBusinesses = new ArrayList<Business>();
//Provide a reference to the type of views that you are using
//(custom viewholder)
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextViewName;
public TextView mTextViewDescription;
public ImageView mImageViewLogo;
public ViewHolder(View v) {
super(v);
mTextViewName = (TextView) v
.findViewById(R.id.textView_company_name);
mTextViewDescription = (TextView) v
.findViewById(R.id.textView_company_description);
mImageViewLogo = (ImageView) v
.findViewById(R.id.imageView_company_logo);
}
}
//Provide a suitable constructor (depends on the kind of dataset)
public BusinessAdapter(List<Business> myBusinesses) {
Log.d(Const.DEBUG, "BusinessAdapter -> constructor");
mBusinesses = myBusinesses;
}
//Create new views (invoked by the layout manager)
@Override
public BusinessAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
Log.d(Const.DEBUG, "BusinessAdapter -> onCreateViewHolder()");
//create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_business_list, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
//Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//- get element from your dataset at this position
//- replace the contents of the view with that element
Log.d(Const.DEBUG, "BusinessAdapter -> onBindViewHolder()");
Business item = mBusinesses.get(position);
holder.mTextViewName.setText(item.getName());
holder.mTextViewDescription.setText(item.getDescription());
holder.mImageViewLogo.setImageResource(R.drawable.ic_launcher);
}
//Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
Log.d(Const.DEBUG, "BusinessAdapter -> getItemCount()");
if (mBusinesses != null) {
Log.d(Const.DEBUG, "mBusinesses Count: " + mBusinesses.size());
return mBusinesses.size();
}
return 0;
}
}

Pero no tengo los datos que se muestran en la vista. ¿Qué estoy haciendo mal?

Aquí está mi log,

07-14 21:15:35.669: D/xxx(2259): Dummy Data Inserted
07-14 21:15:35.669: D/xxx(2259): Businesses Length: 3
07-14 21:26:26.969: D/xxx(2732): BusinessAdapter -> constructor

No tengo los registros después de esto. No getItemCount() en el adaptador debe ser llamado de nuevo?

InformationsquelleAutor Vamsi Challa | 2014-07-14

5 Comentarios

  1. 63

    En su parseResponse() está creando una nueva instancia de la BusinessAdapter clase, pero que en realidad no son de usar en cualquier lugar, por lo que su RecyclerView no sabe la nueva instancia existe.

    Usted necesita:

    • Llamada recyclerView.setAdapter(mBusinessAdapter) de nuevo para actualizar el RecyclerView del adaptador de referencia para apuntar a la nueva
    • O simplemente eliminar mBusinessAdapter = new BusinessAdapter(mBusinesses); para continuar utilizando el adaptador existente. Dado que no ha cambiado la mBusinesses de referencia, el adaptador todavía el uso de la matriz de la lista y actualizar correctamente cuando llame notifyDataSetChanged().
    • Gracias por su ayuda!!! Lo tengo.. solo elimina la línea que crea una nueva instancia de nuevo. Aceptará su respuesta en 8 minutos.
    • Este no me funciona, he tenido que recrate el adaptador y la puso de nuevo a la recylerview
    • Estoy siguiendo tu segundo punto, al crear el adaptador de nuevo con el nuevo BusinessAdapter(mBusinesses). ¿Tengo que liberar el adaptador de alguna manera? Será esto causa una pérdida de memoria si sigo la creación de un nuevo adaptador de cada vez?
    • Mientras usted no está estáticamente referencia a nada o de lo contrario, aferrarse a las referencias, puede dejar que la edad de referencia que ir.
    • Sólo tienes que encontrar la posición donde se agregan o eliminan los datos de su lista utilizando int index = list.indexOf(object) y según ese índice puede notificar a los datos utilizando adapter.notifyItemChanged(index)
    • He creado un método setData en el Adaptador, y aprobó la actualización de la lista y, a continuación, llamé a setAdapter(mAdapter); y funcionó
    • Hola @Tanis.7x estoy atascado con un problema similar.También he publicado una pregunta en stackoverflow stackoverflow.com/questions/43893288/… .Yo espero que usted sea capaz de ayudarme.Gracias.

  2. 24

    Probar este método:

    List<Business> mBusinesses2 = mBusinesses;
    mBusinesses.clear();
    mBusinesses.addAll(mBusinesses2);
    //and do the notification

    un poco de tiempo, pero debería funcionar.

    • Esta declaración: Lista de<Negocios> mBusinesses2 = mBusinesses; que no hacer una copia profunda de la lista. Así que no eres la clonación de la lista – que es una cosa, la segunda cosa es que yo no veo cómo esto podría resolver el problema original….
    • En realidad, yo tenía un problema similar y lo resolvió de esta manera: solution
    • Sin embargo, lo hace
  3. 4

    Yo tenía el mismo problema. Me acaba de resolver con declarar adapter público antes de onCreate de clase.

    PostAdapter postAdapter;

    después de que

    postAdapter = new PostAdapter(getActivity(), posts);
    recList.setAdapter(postAdapter);

    por fin me han llamado:

    @Override
    protected void onPostExecute(Void aVoid) {
    super.onPostExecute(aVoid);
    //Display the size of your ArrayList
    Log.i("TAG", "Size : " + posts.size());
    progressBar.setVisibility(View.GONE);
    postAdapter.notifyDataSetChanged();
    }

    Puede que esto le ayuda a usted.

  4. 2

    Sólo para complementar las otras respuestas no creo que nadie mencionó esta aquí: notifyDataSetChanged() deben ser ejecutadas en el hilo principal (otros notify<Something> métodos de RecyclerView.Adapter así, por supuesto)

    De lo que deduzco, ya que tiene el análisis de los procedimientos y de la llamada a notifyDataSetChanged() en el mismo bloque, ya sea que usted está llamando desde un subproceso de trabajo, o estás haciendo JSON de análisis en el hilo principal (que es también un no-no, como estoy seguro que usted sabe). Así que la forma correcta sería:

    protected void parseResponse(JSONArray response, String url) {
    //insert dummy data for demo
    //<yadda yadda yadda>
    mBusinessAdapter = new BusinessAdapter(mBusinesses);
    //or just use recyclerView.post() or [Fragment]getView().post()
    //instead, but make sure views haven't been destroyed while you were
    //parsing
    new Handler(Looper.getMainLooper()).post(new Runnable() {
    public void run() {
    mBusinessAdapter.notifyDataSetChanged();
    }
    });

    }

    PS cosa Extraña es, no creo que usted recibe indicaciones sobre el hilo principal cosa de IDE o tiempo de ejecución de los registros. Esto es sólo a partir de mis observaciones personales: si hago la llamada notifyDataSetChanged() de un subproceso de trabajo, no entiendo la obligatoria Sólo el hilo original que creó una jerarquía puede tocar sus puntos de vista mensaje ni nada de eso, es sólo falla en silencio (y en mi caso uno fuera de la principal-subproceso de llamada puede incluso impedir el éxito principal de la rosca de llamadas funciona correctamente, probablemente debido a algún tipo de condición de carrera)

    Por otra parte, ni el RecyclerView.Adaptador de referencia de la api ni el oficial correspondiente dev guía menciona explícitamente el hilo principal requisito en el momento (el momento es de 2017) y ninguno de los Android Studio pelusa reglas de inspección parecen preocupación por este problema.

    Pero, aquí está una explicación de este por el mismo autor

    • Hombre muchas gracias! De todas las cosas que he intentado, el tuyo funcionó a la perfección.
    • me alegra poder ayudar, compañero

Dejar respuesta

Please enter your comment!
Please enter your name here