如何从 RecyclerView.Adapter 中的 ViewHolder 调用 MainActivity 方法? [英] How to call a MainActivity method from ViewHolder in RecyclerView.Adapter?

查看:25
本文介绍了如何从 RecyclerView.Adapter 中的 ViewHolder 调用 MainActivity 方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

MainActivity.java 包含一个要调用的方法,当用户在 RecyclerView 中点击蓝牙设备时:

public void confirmConnection(String address) {最终的蓝牙设备设备 = mBluetoothAdapter.getRemoteDevice(address);AlertDialog.Builder builder = new AlertDialog.Builder(this);builder.setMessage("你要配对到" + device + "吗?");builder.setPositiveButton(R.string.button_ok,新 DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int id) {device.createBond();}});builder.setNegativeButton(R.string.button_cancel, null);builder.show();}

ViewHolder 类中(在 DeviceListAdapter.java) 点击监听器定义:

public class DeviceListAdapter extendsRecyclerView.Adapter{私有 ArrayListmDevices = new ArrayList();受保护的静态类 ViewHolder扩展 RecyclerView.ViewHolder实现 View.OnClickListener {私有 TextView 设备地址;公共 ViewHolder(View v) {超级(五);v.setOnClickListener(this);}@覆盖public void onClick(View v) {字符串地址 = deviceAddress.getText().toString();Toast.makeText(v.getContext(),"如何调用 MainActivity.confirmConnection(address)?",Toast.LENGTH_SHORT).show();}}

我的问题:

如何从ViewHolderonClick方法调用confirmConnection(address)方法?

我一直在 2 个 Java 文件之间移动 ViewHolder 类声明,并尝试将其放入自己的文件中 - 只是找不到正确的方法.

我是否应该向 ViewHolder 类添加一个字段并(何时?)在那里存储对 MainActivity 实例的引用?

更新:

这对我有用,但似乎是一种解决方法(而且我也在考虑使用 LocalBroadcastReceiver - 这将是一种更加hackish 的解决方法)-

 @Overridepublic void onClick(View v) {字符串地址 = deviceAddress.getText().toString();尝试 {((MainActivity) v.getContext()).confirmConnection(address);} 捕获(异常 e){//忽略}}

解决方案

为了保持类解耦,我建议在适配器上定义一个接口,例如:

公共接口 OnBluetoothDeviceClickedListener {void onBluetoothDeviceClicked(String deviceAddress);}

然后在您的适配器中为此添加一个 setter:

private OnBluetoothDeviceClickedListener mBluetoothClickListener;public void setOnBluetoothDeviceClickedListener(OnBluetoothDeviceClickedListener l) {mBluetoothClickListener = l;}

然后在内部,在您的 ViewHolderonClick() 中:

if (mBluetoothClickListener != null) {最终字符串地址 = deviceAddress.getText().toString();mBluetoothClickListener.onBluetoothDeviceClicked(地址);}

然后让您的 MainActivity 将侦听器传递给 Adapter:

mDeviceListAdapter.setOnBluetoothDeviceClickedListener(new OnBluetoothDeviceClickedListener() {@覆盖public void onBluetoothDeviceClicked(String deviceAddress) {确认连接(设备地址);}});

通过这种方式,您可以稍后重用适配器,而无需将其绑定到特定行为.

In a simple app project at GitHub I have only 2 custom Java-files:

  1. MainActivity.java contains Bluetooth- and UI-related source code
  2. DeviceListAdapter.java contains an Adapter and ViewHolder for displaying Bluetooth devices in a RecyclerView

The MainActivity.java contains a method to be called, when user taps on a Bluetooth device in the RecyclerView:

public void confirmConnection(String address) {
    final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("Do you want to pair to " + device + "?");
    builder.setPositiveButton(R.string.button_ok, 
      new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
            device.createBond();
        }
    });
    builder.setNegativeButton(R.string.button_cancel, null);
    builder.show();
}

And in the ViewHolder class (in the DeviceListAdapter.java) the click listener is defined:

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

  private ArrayList<BluetoothDevice> mDevices = new ArrayList<BluetoothDevice>();

  protected static class ViewHolder
        extends RecyclerView.ViewHolder
        implements View.OnClickListener {

    private TextView deviceAddress;

    public ViewHolder(View v) {
        super(v);
        v.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        String address = deviceAddress.getText().toString();

        Toast.makeText(v.getContext(),
                "How to call MainActivity.confirmConnection(address)?",
                Toast.LENGTH_SHORT).show();
    }
  }

My problem:

How to call confirmConnection(address) method from ViewHolders onClick method?

I keep moving ViewHolder class declaration between the 2 Java files and also tried putting it into its own file - and just can't find the right way.

Should I maybe add a field to ViewHolder class and (when?) store a reference to MainActivity instance there?

UPDATE:

This works for me, but seems to be a workaround (and also I was thinking of using LocalBroadcastReceiver - which would be an even more hackish workaround) -

    @Override
    public void onClick(View v) {
        String address = deviceAddress.getText().toString();

        try {
            ((MainActivity) v.getContext()).confirmConnection(address);
        } catch (Exception e) {
            // ignore
        }
    }

解决方案

To keep your classes decoupled, I'd suggest defining an interface on your adapter, something like:

public interface OnBluetoothDeviceClickedListener {
    void onBluetoothDeviceClicked(String deviceAddress);
}

Then add a setter for this in your adapter:

private OnBluetoothDeviceClickedListener mBluetoothClickListener;

public void setOnBluetoothDeviceClickedListener(OnBluetoothDeviceClickedListener l) {
    mBluetoothClickListener = l;
}

Then internally, in your ViewHolder's onClick():

if (mBluetoothClickListener != null) {
    final String addresss = deviceAddress.getText().toString();
    mBluetoothClickListener.onBluetoothDeviceClicked(address);
}

Then just have your MainActivity pass in a listener to the Adapter:

mDeviceListAdapter.setOnBluetoothDeviceClickedListener(new OnBluetoothDeviceClickedListener() {
    @Override
    public void onBluetoothDeviceClicked(String deviceAddress) {
        confirmConnection(deviceAddress);
    }
});

This way you can reuse the adapter later without it being tied to that particular behavior.

这篇关于如何从 RecyclerView.Adapter 中的 ViewHolder 调用 MainActivity 方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆