Cómo utilizar notifydatasetchanged in recyclerview gridlayout

Soy nuevo en android y tratando de actualizar el gridlayout en películas populares aplicación de películas populares de udacity nanodegree proyecto.

Estoy descargando los datos usando AsyncTask y analizando los datos, actualizando el recyclerview y ajustando el adaptador en onPostExecute .

Esta es mi clase AsyncTask

 private class getJson extends AsyncTask<String, Void, String>{ @Override protected String doInBackground(String... strings) { String result = ""; URL url; HttpURLConnection httpURLConnection = null; try { url = new URL(strings[0]); httpURLConnection = (HttpURLConnection) url.openConnection(); InputStream in = httpURLConnection.getInputStream(); InputStreamReader reader = new InputStreamReader(in); int data = reader.read(); while ( data != -1 ){ char current = (char) data; result += current; data = reader.read(); } } catch (java.io.IOException e) { e.printStackTrace(); } return result; } @Override protected void onPostExecute(String s) { super.onPostExecute(s); jsonString = s; Log.i("result", jsonString); JSONObject jsonObject = null; if(!list.isEmpty()) list.clear(); try { jsonObject = new JSONObject(jsonString); JSONArray jsonArray = jsonObject.getJSONArray("results"); for( int i = 0; i < jsonArray.length() && i < 10; i++ ){ JSONObject currObject = jsonArray.getJSONObject(i); String posterurl = preUrl + currObject.getString("backdrop_path"); Log.i("poster", posterurl); String url = preUrl + currObject.getString("poster_path"); String overview = currObject.getString("overview"); String title = currObject.getString("original_title"); String release_date = (currObject.getString("release_date")); String votes = (currObject.getString("vote_average")); list.add(new MovieDetails(url,overview, title, release_date, votes, posterurl)); } } catch (JSONException e) { e.printStackTrace(); } } } 

Esta es mi clase de adaptador

  public class MainRecyclerViewAdapter extends RecyclerView.Adapter<MainRecyclerViewAdapter.ViewHolder> { ArrayList<MovieDetails> data; Context context; public MainRecyclerViewAdapter(Context context, ArrayList<MovieDetails> data ){ this.data = data; this.context = context; } @Override public MainRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false); MainRecyclerViewAdapter.ViewHolder viewHolder = new MainRecyclerViewAdapter.ViewHolder(v); return viewHolder; } @Override public void onBindViewHolder(MainRecyclerViewAdapter.ViewHolder holder, int position) { Picasso.with(context).load(data.get(position).getImageUrl()).into(holder.movie_thumbnail); //holder.movie_thumbnail.setImageResource(R.mipmap.ic_launcher); } @Override public int getItemCount() { return data.size(); } public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ ImageView movie_thumbnail; private Context context; @Override public void onClick(View view) { Toast.makeText(context,data.get(getPosition()).getTitle(),Toast.LENGTH_LONG).show(); Intent intent = new Intent(context, DetailsActivity.class); Bundle bundle = new Bundle(); bundle.putSerializable("list", (Serializable) data); intent.putExtras(bundle); intent.putExtra("index", getAdapterPosition()); context.startActivity(intent); } public ViewHolder(View itemView) { super(itemView); context = itemView.getContext(); itemView.setOnClickListener(this); movie_thumbnail = (ImageView) itemView.findViewById(R.id.movies_item_thumbnail); } } } 

Así es como estoy manejando la clasificación basada en la votación o la popularidad

 @Override public boolean onOptionsItemSelected(MenuItem item) { getJson gJson = new getJson(); switch (item.getItemId()){ case R.id.rating : gJson.execute(top_rated); return true; case R.id.popularity : gJson.execute(popular); return true; default: return super.onOptionsItemSelected(item); } } 

Crecer

 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar myToolbar = (Toolbar) findViewById(R.id.main_toolbar); setSupportActionBar(myToolbar); getJson getJson = new getJson(); getJson.execute(popular); recyclerView = (RecyclerView)findViewById(R.id.main_recyclerview); recyclerView.setHasFixedSize(true); layoutManager = new GridLayoutManager(MainActivity.this,2); recyclerView.setLayoutManager(layoutManager); adapter = new MainRecyclerViewAdapter(MainActivity.this, list); recyclerView.setAdapter(adapter); } 

Me imaginé usar notifydatasetchanged() , pero no soy capaz de calcular dónde usar eso.

También por favor dígame la mejor manera de manejar la clasificación.

Esto es lo que hice :

  1. Moví la instancia del adaptador y el ajuste del adaptador de a onCreate
  2. Llamando notfiydatasetchanged() en onPostexeute()

  3. Cada vez que llamo a AsyncTask , mi arraylist se está poblando con nuevos elementos y por lo que el adaptador está llenando todas las imágenes. Soy list.clear() antes de analizar el json en onPostexecute()

Aquí está todo lo que usted necesita hacer,

Mira mi ejemplo

Estos son vars globales

  private List<Movie> movieList = new ArrayList<>(); private RecyclerView recyclerView; private MoviesAdapter mAdapter; 

Vamos a onCreate

1.initialize recycle view

 recyclerView = (RecyclerView) findViewById(R.id.recycler_view); 

2.create nueva instancia de mi lista

 mAdapter = new MoviesAdapter(movieList); 

3.set up my recycle ver

  RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext()); recyclerView.setLayoutManager(mLayoutManager); recyclerView.setItemAnimator(new DefaultItemAnimator()); 

4.set el adaptador a mi recycleView

 recyclerView.setAdapter(mAdapter); 

5.Call el método para cargar los datos.

 setMyData(); 

Vamos al método setMyData

1.get datos de alguna manera .. puede ser sever

2.add ellos a mi lista

 movieList.add(movie); // i have not added the lines where i add data to my movie list think it has 10 elements now 

3.después de añadir todos los datos realizo un

 mAdapter.notifyDataSetChanged(); 

Así que cada vez que hay un cambio puedo llamar a setMyData(); Establece datos según sea necesario.

¿Qué tal esa lógica?

A propósito no añadir la clase de adaptador, si usted necesita que también me dejó saber

Sugerencia: ¿ su tarea asíncrona debería hacer lo que hace el método setMyData() ? ahora ve. ¡De acuerdo, necesitas actualizar tus datos por segunda vez! Vaya a su tarea async, layoutManager = new GridLayoutManager(MainActivity.this,2);

Ah ha llamar a esta línea una y otra vez cuando se llama a su tarea asíncrona … la gente le sugiere notificar a DataSet en onPostExecute , (funciona pero ..) pensar, nuevo objeto también se crea tan tan !! Llame a su asyncTask 10 veces .. ahora comparar donde he creado mi objeto, no que siga aumentando .. ahora se verá lo que salió mal!

Ps mi instancia LayoutManager no está en mi método setMyData() pero en mi onCreate

Como sugirió Cory Roy , prueba esto:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView)findViewById(R.id.main_recyclerview); layoutManager = new GridLayoutManager(MainActivity.this, 2); recyclerView.setLayoutManager(layoutManager); adapter = new MainRecyclerViewAdapter(MainActivity.this, list); recyclerView.setAdapter(adapter); } private class getJson extends AsyncTask<String, Void, String>{ @Override protected String doInBackground(String... strings) { String result = ""; URL url; HttpURLConnection httpURLConnection = null; try { url = new URL(strings[0]); httpURLConnection = (HttpURLConnection) url.openConnection(); InputStream in = httpURLConnection.getInputStream(); InputStreamReader reader = new InputStreamReader(in); int data = reader.read(); while ( data != -1 ){ char current = (char) data; result += current; data = reader.read(); } } catch (java.io.IOException e) { e.printStackTrace(); } return result; } @Override protected void onPostExecute(String s) { super.onPostExecute(s); jsonString = s; Log.i("result", jsonString); JSONObject jsonObject = null; try { jsonObject = new JSONObject(jsonString); JSONArray jsonArray = jsonObject.getJSONArray("results"); for( int i = 0; i < jsonArray.length() && i < 10; i++ ){ JSONObject currObject = jsonArray.getJSONObject(i); String posterurl = preUrl + currObject.getString("backdrop_path"); Log.i("poster", posterurl); String url = preUrl + currObject.getString("poster_path"); String overview = currObject.getString("overview"); String title = currObject.getString("original_title"); String release_date = (currObject.getString("release_date")); String votes = (currObject.getString("vote_average")); list.add(new MovieDetails(url,overview, title, release_date, votes, posterurl)); } } catch (JSONException e) { e.printStackTrace(); } adapter.notifyDataSetChanged(); } } 

Por favor, inténtelo y hágamelo saber si funciona.

Para las solicitudes de http que aconsejo utilizar retrofit . El adaptador describe la función de clasificación en las opciones que desea, notifydatasetchanged(); y al final notifydatasetchanged();

por ejemplo

 void sort(String sortBy) { // your sort notifydatasetchanged(); } 

Cuando quiera usar el orden simplemente llame a un método de clasificación del adapter , defina los datos en él.

Usted está utilizando un AsyncTask para descargar películas desde un servidor remoto. Una vez finalizada la descarga y el análisis, cree el adaptador y RecyclerView el RecyclerView

Según su implementación no es necesario llamar a notifyDataSetChanged() en postExecute ()

El acercamiento anterior tiene una desventaja que usted crea una nueva instancia del adaptador cada vez que el AsyncTask ejecuta.

Prueba algo más abajo

  Activity { ArrayList<MovieDetails> data; MainRecyclerViewAdapter adapter onCreate() { recyclerView = (RecyclerView)findViewById(R.id.main_recyclerview); recyclerView.setHasFixedSize(true); layoutManager = new GridLayoutManager(MainActivity.this,2); recyclerView.setLayoutManager(layoutManager); adapter = new MainRecyclerViewAdapter(MainActivity.this); recyclerView.setAdapter(adapter); } AsyncTask { /..... onPostExecute{ // Download completed adapter.notifyDataSetChanged() } } MainRecyclerViewAdapter { //... ViewHolder { //... } } } 

Establezca el adapter en el onCreate de la actividad.

  adapter = new MainRecyclerViewAdapter(MainActivity.this, list); recyclerView.setAdapter(adapter); 

Utilice un campo para almacenar su lista.

Llame a notifydatasetchanged() en el onPostExecute() del AsyncTask (como lo está haciendo), pero no AsyncTask asignar el adapter allí.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.