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
.
- Cómo manejar clics de artículo para una vista de reciclar usando RxJava
- Listview y volley - imagen incorrecta asignada
- RecyclerView wrap_content
- Agregar márgenes al divisor en RecyclerView
- Cómo configurar RecyclerView en el widget android
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 :
- Moví la instancia del adaptador y el ajuste del adaptador de a onCreate
-
Llamando
notfiydatasetchanged()
enonPostexeute()
-
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. Soylist.clear()
antes de analizar el json enonPostexecute()
- Altura de la barra de herramientas de Android al desplazarse
- RecyclerView: IndexOutOfBoundsException Inconsistencia detectada. Posición de artículo no válida
- Centrar elementos en un RecyclerView cuando se implementa con GridLayoutManager
- Inflating RecyclerView en DialogFragment IllegalStateException
- ¿Cómo agregar divisores y espacios entre los elementos de RecyclerView?
- Deslizar a otra vista en recyclerVer con ItemTouchHelper
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í.