【问题标题】:RecyclerView Onclick (call non-static method)RecyclerView Onclick(调用非静态方法)
【发布时间】:2015-05-27 16:35:26
【问题描述】:

我遇到了一个关于为我的 RecyclerView 项目设置 OnItemClickListener 的问题。我尝试按照 Android Studio 的 RecyclerView 示例中描述的方式设置监听器。所以在 ViewHolder 类中为我的 RecyclerView 设置了一个监听器。

public class ProgramViewHolder extends RecyclerView.ViewHolder {
    protected TextView vName;
    protected ImageView vProgramImage;

    public ProgramViewHolder(View v) {
        super(v);
        vName = (TextView) v.findViewById(R.id.programName);
        vProgramImage = (ImageView) v.findViewById(R.id.programImage);

        v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // HERE PROBLEM !! 
                MainActivity.openSettings(1);
            }
        });
    }
}

现在我想调用我的 MainActivity openSettings(int) 的一个方法来加载片段:

public void openSettings(int layoutId) {
    settingsFragment setFrag = new settingsFragment();

    Bundle information = new Bundle();
    information.putInt("layoutId", layoutId);

    setFrag.setArguments(information);
    getFragmentManager().beginTransaction()
            .replace(R.id.fragmentContainer, setFrag)
            .commit();
}

但是现在问题来了。当我尝试编译时,它说“不能从静态上下文引用非静态方法 'openSettings(int)'。” 我完全不明白这个错误。为什么它是静态上下文? ProgramViewHolder 类没有声明为静态的。

还有最重要的部分:我该如何解决?我想为 RecyclerView 的每个项目设置一个 OnClickListener 并调用 MainActivity 的公共方法。

非常感谢您花时间帮助我。

【问题讨论】:

  • MainActivity.this.openSettings(1) ?
  • 为什么不将打开的设置移动到处理程序类?
  • 然后它说,“'MainActivity' 不是封闭类。
  • 好吧,我想我需要从 MainActivity 中获取 FragmentManager。据我了解,我无法从 Adapter 类中调用 getFragmentManager() ..

标签: java android static onclick android-recyclerview


【解决方案1】:

这并不是说 ProgramViewHolder 是静态的,而是因为试图从静态上下文调用您的活动(您没有调用活动的特定实例)。

您应该做的是将活动传递到您的 recyclerViewAdapter 以便您可以访问它。

例如

MainActivity mainActivity;
public CustomRecyclerViewAdapter(MainActivity mainActivity) {
    this.mainActivity = mainActivity;
}

并从 MainActivity 创建 recyclerViewAdapter CustomRecyclerView recyclerViewAdapter = new CustomRecyclerViewAdapter(this); recyclerViewAdapter.setAdapter(recyclerViewAdapter);

然后您应该能够像这样访问您的方法 mainActivity.openSettings(1);

如果你有任何问题,请告诉我

//编辑

以下是从 bindViewHolder 设置 onClick 的方法。由于 RecyclerView “回收”数据的方式,您想在此处设置任何 onClickListeners。例如,如果每一行都应在单击时执行不同的操作,则需要确保单击侦听器绑定到特定行。在 onBindViewHolder 中创建它可以确保这一点。如果您希望整行是可点击的,而不是里面的元素,只需创建一个填充整行的外部视图。然后将 onClickListener 绑定到那个。

// 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

    ProgramViewHolder programViewHolder = (ProgramViewHolder) holder;
    programViewHolder.vName.setOnClicklistener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mainActivity.openSettings(1);
        }
    });

}

【讨论】:

  • 好的,我明白了。但我不明白解决方案。我应该在哪里写第一个sn-p?我的 RecyclerView 是在 XML 文件中创建的。那不是更好吗?如何传递我的 MainActivity 实例?
  • 我刚刚编辑了答案。我的意思是告诉你将活动传递给 recyclerView 适配器。我假设您有一个包含 ProgramViewHolder 的 recyclerView 适配器?
  • 另外,对于 RecyclerView,您不应该从 ViewHolder 创建 onClick 侦听器。它应该在 onBindViewHolder 中创建。请参阅此链接以了解如何正确创建适配器。 developer.android.com/training/material/lists-cards.html
  • 您的意思是我应该将 OnClickListener 设置为特定视图,例如 vName 或 vProgramImage?这有什么好处?非常感谢您的帮助!
  • 甜蜜!很高兴我能帮上忙!
【解决方案2】:

如果你有context的activity包含recyclerView,那么你可以简单地这样做:

your_view_holder.v.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // HERE SOLUTION!! 
                ((MainActivity)context).openSettings(1);
            }
        });

你可以把它放在onBindViewHolder(...)

如何获取上下文:

在适配器的构造函数中创建另一个上下文参数,并在实例化适配器后从活动中传递上下文。

为什么要传递上下文:

我建议您始终传递上下文并将其分配给任何适配器的变量,因为这是您在使用适配器时不时需要的东西,因此不要每次都使用解决方法来获取上下文,只需保存一次.

【讨论】:

    猜你喜欢
    • 2013-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-08
    • 2016-10-04
    相关资源
    最近更新 更多