从适配器调用Activity方法

use*_*687 112 android list adapter addressing

是否可以调用Activityfrom中定义的方法ListAdapter

(我想打一个Buttonlist's行单击此按钮时,它应该执行的方法,即在相应的活动定义.我试图设置onClickListener在我ListAdapter,但我不知道该怎么称呼这种方法,什么是它的路径. ..)

当我使用时,Activity.this.method()我收到以下错误:

No enclosing instance of the type Activity is accessible in scope
Run Code Online (Sandbox Code Playgroud)

任何的想法 ?

Eld*_*abu 289

是的你可以.

在适配器中添加一个新字段:

private Context mContext;
Run Code Online (Sandbox Code Playgroud)

在适配器构造函数中添加以下代码:

public AdapterName(......, Context context) {
  //your code.
  this.mContext = context;
}
Run Code Online (Sandbox Code Playgroud)

在适配器的getView(...)中:

Button btn = (Button) convertView.findViewById(yourButtonId);
btn.setOnClickListener(new Button.OnClickListener() {
  @Override
  public void onClick(View v) {
    if (mContext instanceof YourActivityName) {
      ((YourActivityName)mContext).yourDesiredMethod();
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

替换为您自己的类名,您可以在其中查看代码,活动等.

如果您需要将同一个适配器用于多个活动,那么:

创建一个接口

public interface IMethodCaller {
    void yourDesiredMethod();
}
Run Code Online (Sandbox Code Playgroud)

在此方法调用功能所需的活动中实现此接口.

然后在Adapter getView()中,调用如下:

Button btn = (Button) convertView.findViewById(yourButtonId);
btn.setOnClickListener(new Button.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mContext instanceof IMethodCaller) {
            ((IMethodCaller) mContext).yourDesiredMethod();
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

你完成了.如果您需要将此适配器用于不需要此调用机制的活动,则代码将不会执行(如果检查失败).

  • 由于这是一个受欢迎的问题,我强烈建议不要使用此解决方案.您应该避免在此处进行类转换,因为这可能会导致运行时异常. (27认同)
  • Eldhose兄弟,我没有反对你,但下面回答是最好的做法.你甚至可以阅读评论.您不应该将mContext强制转换为Activity,因为您要避免重用代码.现在,此适配器只能在您将mContext变量转换为的Activity中使用,如果您定义了侦听器,则可以在另一个Activity中重用相同的Adapter.相信我,我已经在工业上花了足够的时间,我只是想在这里帮助你,请不要亲自接受. (3认同)
  • 这个解决方案是我在 SO 上找到的最好的解决方案之一。非常感谢巴布先生。通过这种方式调用 Activity 的方法,使整个应用程序的性能提高了 500% -> 我不需要在适配器中重新加载数据库,我需要访问它。我不在乎“行业年限”,我正在寻找稳定且有效的解决方案,而且我很确定,我找不到更好的访问方式。也许我可以将数据库设置为单例,但这不是我想要“解构”我的项目的方式。 (2认同)
  • @RAM如果需要在多个活动中调用相同的方法,则需要创建具有该方法名称的接口.然后在您需要方法调用的所有活动中实现该接口.然后在单击侦听器中,检查接口的实例,而不是使用活动名称. (2认同)

Igo*_*pov 118

你可以这样做:

声明接口:

public interface MyInterface{
    public void foo();
}
Run Code Online (Sandbox Code Playgroud)

让你的活动改变它:

public class MyActivity extends Activity implements MyInterface{
    public void foo(){
        //do stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将您的活动传递给ListAdater:

public MyAdapter extends BaseAdater{
    private MyInterface listener;

    public MyAdapter(MyInterface listener){
        this.listener = listener;
    }
}
Run Code Online (Sandbox Code Playgroud)

在适配器的某个地方,当你需要调用那个Activity方法时:

listener.foo();
Run Code Online (Sandbox Code Playgroud)

  • 我首先想到了上面的方法,就像使用片段一样,但这是最好的解决方案! (5认同)
  • 如何将接口传递给适配器(来自Activity) (5认同)
  • @Brandon,只需添加'this'即可将接口传递给适配器myAdapter = new MyAdapter(this); (5认同)
  • 我的适配器中的 NullPointerException 扩展了 RealmBaseAdapter (2认同)

Jar*_*ows 60

原版的:

我理解当前的答案,但需要一个更清晰的例子.这是我使用Adapter(RecyclerView.Adapter)和一个例子Activity.

在您的活动中:

这将实现interface我们所拥有的Adapter.在此示例中,将在用户单击中的项目时调用它RecyclerView.

public class MyActivity extends Activity implements AdapterCallback {

    private MyAdapter myAdapter;

    @Override
    public void onMethodCallback() {
       // do something
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        myAdapter = new MyAdapter(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的适配器中:

Activity,我们启动了我们Adapter并将其作为构造函数的参数传递.这将启动我们interface的回调方法.您可以看到我们使用回调方法进行用户点击.

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    private AdapterCallback adapterCallback;

    public MyAdapter(Context context) {
        try {
            adapterCallback = ((AdapterCallback) context);
        } catch (ClassCastException e) {
            throw new ClassCastException("Activity must implement AdapterCallback.", e);
        }
    }

    @Override
    public void onBindViewHolder(MyAdapter.ViewHolder viewHolder, int position) {
        // simple example, call interface here
        // not complete
        viewHolder.itemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    adapterCallback.onMethodCallback();
                } catch (ClassCastException e) {
                   // do something
                }
            }
        });
    }

    public static interface AdapterCallback {
        void onMethodCallback();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你,这正是我想要的.上投 (6认同)
  • 这个答案应该有更多的赞成,这是一个干净而完美的解决方案. (3认同)
  • 谢谢你的解决方案 (2认同)

Ck *_*rya 12

基本而简单.

在你的适配器中使用它.

((YourParentClass)context).functionToRun();

  • 不是一个好的做法,因为你限制你的类只使用YourParentClass类型而不是任何类,但如果你不关心重用它,如果你也重命名一个类代码中断... (4认同)

Pra*_*war 7

还有一种方法是::

在你的适配器中写一个方法让我们说public void callBack(){}.

现在,为活动中的适配器创建对象时,会覆盖此方法.在适配器中调用方法时,将调用覆盖方法.

Myadapter adapter = new Myadapter() {
  @Override
  public void callBack() {
    // dosomething
  }
};
Run Code Online (Sandbox Code Playgroud)


Num*_*air 6

对于科特林:

在您的适配器中,只需调用

(context as Your_Activity_Name).yourMethod()
Run Code Online (Sandbox Code Playgroud)