Actualizar actividad onclick en RecyclerView

Tengo una actividad compuesta por 2 elementos principales: un RecyclerView y un ListView. RecyclerView actúa como un filter y seleccionar / deseleccionar elementos afectará el contenido de ListView. Todo funciona bien hasta que intenté implementar onClickListener en el RecyclerView y me di count de que no era una opción.

He intentado ir por la ruta de configurar un OnClickListener dentro de ViewHolder, pero necesita llamar a una function dentro de la actividad principal y actualizar su listView. Cualquier interacción de este tipo desencadena el siguiente error:

java.lang.NullPointerException at android.support.v7.app.AppCompatDelegateImplBase.<init>(AppCompatDelegateImplBase.java:117) at android.support.v7.app.AppCompatDelegateImplV9.<init>(AppCompatDelegateImplV9.java:149) at android.support.v7.app.AppCompatDelegateImplV11.<init>(AppCompatDelegateImplV11.java:29) at android.support.v7.app.AppCompatDelegateImplV14.<init>(AppCompatDelegateImplV14.java:54) at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:202) at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:183) at android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:519) at android.support.v7.app.AppCompatActivity.findViewById(AppCompatActivity.java:190) at .newsScreen._$_findCachedViewById(newsScreen.kt) at .newsScreen.filterNews(newsScreen.kt:71) at Cells.NewsFeedList$NewsSource$1.onClick(News Lists.kt:84) 

Supongamos que tiene sentido ya que bash acceder a UI desde fuera de su class, pero no pude encontrar alternativas.

Adaptador RecyclerView:

 class NewsFeedList() : RecyclerView.Adapter<NewsFeedList.NewsSource>() { private var source: List<NewsFeed> = ArrayList() constructor(s: ArrayList<NewsFeed>) : this() { source = s } class NewsSource : RecyclerView.ViewHolder { private var mTextView: TextView? = null constructor(v: View): super(v) { mTextView = v.title } fun bindInfo(news: NewsFeed, view: View, int: Int) { mTextView!!.text = news.title view.tag = int view.setOnClickListener { newsScreen().filterNews(view.tag.toString().toInt()) } if (news.selected) view.background = ColorDrawable(Color.parseColor(news.color)) else view.background = ColorDrawable(Color.parseColor(design.backgroundColor)) } } override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): NewsFeedList.NewsSource { val view = LayoutInflater.from(parent!!.context).inflate(R.layout.newsfeed_list, parent, false) return NewsSource(view) } override fun onBindViewHolder(holder: NewsFeedList.NewsSource, position: Int) { holder.bindInfo(source[position], holder.itemView, position) } override fun getItemCount(): Int { return source.count() } } 

Luego, dentro de mi class newsScreen, necesito acceder al adaptador RecyclerView con nuevos datos

 fun filterNews(i: Int) { newsFeed[i].selected = !newsFeed[i].selected filter.adapter = NewsFeedList(newsFeed) } 

Si elimino cualquier reference al filter (RecyclerView), todo está bien, pero el objective de onClickListener es actualizar el contenido de las Actividades.

¿Hay alguna manera de lograr esto o debería cambiar el RecyclerView a un elemento de interfaz de usuario diferente?

Editar: He intentado agregar un OnClickListener al RecyclerView, pero parece que no se activó. Código:

 filter.adapter = NewsFeedList(newsFeed) filter.layoutManager = LinearLayoutManager(this@newsScreen, LinearLayoutManager.HORIZONTAL, false) filter.setOnClickListener { v: View? -> filterNews(v!!.tag.toString().toInt()) } 

Bien, aquí hay otra solución que puedes probar:

Agrega esta interfaz a tu aplicación:

 interface ClickListener { void onItemClicked(int position); } 

Impleméntelo dentro de su MainActivity (o en cualquier actividad que tenga los botones).

Pase la reference de la interfaz dentro de su constructor Adaptador: ArrayList mList; ClickListener oyente;

 public MyAdapter(ArrayList<NewsFeed> mList, ClickListener listener) { this.listener = listener; } @Override public MyAdapter.NavViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.someL, parent, false); return new ViewHolder(v, listener); } public void getItemClicked(int position){ mList.get(position); } 

Finalmente, dentro de tu class ViewHolder:

 class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener { TextView textView; ImageView imageView; ClickListener listener; ViewHolder(View itemView, ClickListener listener) { super(itemView); this.listener = listener; textView = (TextView) itemView.findViewById(R.id.text_view); imageView = (ImageView) itemView.findViewById(R.id.image_view); textView.setOnClickListener(this) } @Override void onClick(View v) { listener.onItemClicked(getAdapterPosition()); } 

Y finalmente dentro de tu Actividad (que implementa la interfaz ClickListener) tendrás que anular void onItemClicked(int position); dentro del cual tendrás tu acción.

PD: Esta respuesta fue escrita con gran ayuda del usuario: https://stackoverflow.com/users/2667883/chaynik

Para su class de adaptador tendrá una class ViewHolder (probablemente como una class interna) que implementa OnClickListener como tal en este código:

 class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener { TextView textView; ImageView imageView; ViewHolder(View itemView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.text_view); imageView = (ImageView) itemView.findViewById(R.id.image_view); } @Override void onClick(View v) { } } 

Asumiendo que su Adaptador no es una class interna de su class de Actividad, si está dispuesto con onClick () para acceder a los methods / variables de su class de Actividad, DEBE tener la reference.

La forma preferible es pasar la reference de context a través del constructor de su adaptador, dado que su ViewHolder es una class interna de su adaptador:

 class MyAdapter extends extends RecyclerView.Adapter<RecyclerView.ViewHolder> { Context context; MyAdapter(Context context) { this.context = context; } class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener { TextView textView; ImageView imageView; ViewHolder(View itemView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.text_view); imageView = (ImageView) itemView.findViewById(R.id.image_view); } @Override void onClick(View v) { // Here we gain access to non-private methods/variables // of the Activity, which Context reference we are holding. ((MyActivity) context).someMethod(); } } } 

Espero que esto ayude.