【问题标题】:Refresh Activity when click in RecyclerView在 RecyclerView 中单击时刷新 Activity
【发布时间】:2017-09-19 16:00:03
【问题描述】:

我有一个由 2 个主要项目组成的活动:一个 RecyclerView 和一个 ListView。 RecyclerView 充当过滤器,选择/取消选择其中的项目将影响 ListView 的内容。一切正常,直到我尝试在 RecyclerView 上实现 onClickListener 并意识到这不是一个选项。

我尝试在 ViewHolder 中设置 OnClickListener,但它需要在主 Activity 中调用一个函数并刷新它的 listView。任何此类交互都会触发以下错误:

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)

假设这是有道理的,因为我试图从它的类之外访问 UI,但我找不到它的替代方案。

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()
    }

}

然后,在我的 newsScreen 类中,我需要使用新数据访问 RecyclerView 适配器

fun filterNews(i: Int) {

    newsFeed[i].selected = !newsFeed[i].selected
    filter.adapter = NewsFeedList(newsFeed)

}

如果我删除对过滤器(RecyclerView)的任何引用,一切都很好,但 onClickListener 的目的是刷新活动内容。

有没有办法实现这一点,或者我应该将 RecyclerView 更改为不同的 UI 元素?

编辑: 我尝试将 OnClickListener 添加到 RecyclerView 但它似乎没有被触发。 代码:

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

【问题讨论】:

  • 为什么不使用 OnItemClickListener 而不是 OnClickListener?
  • 你能检查我更新的问题吗?我对 Android 不是很熟悉,所以很明显我错过了一些东西。
  • 很抱歉,OnItemClickListener 实际上并不能很好地与 RecycleView 配合使用。我已经给你写了一个关于如何解决 NullPointerException 问题的答案。

标签: android listview android-recyclerview kotlin


【解决方案1】:

对于您的 Adapter 类,您将拥有一个 ViewHolder 类(可能作为内部类),它在此代码中实现 OnClickListener:

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) {

    }
}

假设您的 Adapter 不是您的 Activity 类的内部类,如果您愿意使用 onClick() 访问您的 Activity 类的方法/变量,您必须有参考。

最好的方法是通过适配器的构造函数传递上下文引用,因为您的 ViewHolder 是适配器的内部类:

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();
        }
    }
}

希望,这会有所帮助。

【讨论】:

  • 这就是我首先得到错误的原因
  • 谢谢,明天回机器更新
  • 我已经用代码更新了我的问题。请注意,它是 Kotlin,而不是 Java,但语法非常相似,我相信这不会是问题 :)
  • 好的,我添加了第二个答案,因为我认为第一个答案可能对其他人有用..我希望能解决你的问题。
  • 我不知道为什么,但这个工作。谢谢@SerjArdovic
【解决方案2】:

好的,你可以试试另一个解决方案:

将此接口添加到您的应用中:

interface ClickListener {
    void onItemClicked(int position);
}

在您的 MainActivity(或您有按钮的任何活动)中实现它。

在 Adapter 构造函数中传递接口的引用: 数组列表 mList; ClickListener 监听器;

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);
}

最后,在 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());
    }

最后,在您的 Activity(实现 ClickListener 接口)中,您必须覆盖 void onItemClicked(int position);,您将在其中执行操作。

P.S.:这个答案是在用户的主要帮助下编写的:https://stackoverflow.com/users/2667883/chaynik

【讨论】:

    【解决方案3】:
    1. 创建一个函数 reload() 并重新加载所有视图
    2. 使用 .this 将您的活动上下文传递给适配器
    3. 在适配器中,将上下文传递给类对象

      MyActivity activity = (MyActivity)context
      

    并像这样调用方法:

    activity.reload();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-10
      • 1970-01-01
      • 2021-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多