![](/img/trans.png)
[英]access RecyclerView.Adapter's method from ViewHolder or ViewModel of ViewHolder
[英]How to call a MainActivity method from ViewHolder in RecyclerView.Adapter?
在GitHub的一個簡單的應用程序項目中,我只有2個自定義Java文件:
Adapter
和ViewHolder
用於在RecyclerView
顯示藍牙設備 當用戶點擊RecyclerView
的藍牙設備時, MainActivity.java包含一個要調用的方法:
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();
}
在ViewHolder
類(在DeviceListAdapter.java中 )中定義了單擊偵聽器:
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();
}
}
我的問題:
如何從ViewHolder
的onClick
方法調用confirmConnection(address)
方法?
我繼續在2個Java文件之間移動ViewHolder
類聲明,並嘗試將其放入自己的文件中 - 並且找不到正確的方法。
我是否應該向ViewHolder
類添加一個字段,並且(當?)存儲對MainActivity
實例的引用?
更新:
這對我LocalBroadcastReceiver
,但似乎是一種解決方法(我也在考慮使用LocalBroadcastReceiver
- 這將是一個更加黑客的解決方法) -
@Override
public void onClick(View v) {
String address = deviceAddress.getText().toString();
try {
((MainActivity) v.getContext()).confirmConnection(address);
} catch (Exception e) {
// ignore
}
}
為了保持類的解耦,我建議在適配器上定義一個接口,例如:
public interface OnBluetoothDeviceClickedListener {
void onBluetoothDeviceClicked(String deviceAddress);
}
然后在適配器中為此添加一個setter:
private OnBluetoothDeviceClickedListener mBluetoothClickListener;
public void setOnBluetoothDeviceClickedListener(OnBluetoothDeviceClickedListener l) {
mBluetoothClickListener = l;
}
然后在內部,在ViewHolder
的onClick()
:
if (mBluetoothClickListener != null) {
final String addresss = deviceAddress.getText().toString();
mBluetoothClickListener.onBluetoothDeviceClicked(address);
}
然后讓您的MainActivity
在Adapter
的監聽Adapter
傳遞:
mDeviceListAdapter.setOnBluetoothDeviceClickedListener(new OnBluetoothDeviceClickedListener() {
@Override
public void onBluetoothDeviceClicked(String deviceAddress) {
confirmConnection(deviceAddress);
}
});
這樣,您可以稍后重用適配器,而不必將其綁定到該特定行為。
對於那些正在尋找從靜態ViewHolder調用回調的人,請執行以下操作。 讓你有一個適配器:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private final int resource;
private final List<Item> items;
private final LayoutInflater inflater;
...
private Callback callback;
private static class ViewHolder extends RecyclerView.ViewHolder {
...
}
public interface Callback {
void onImageClick(int position);
void onRemoveItem(int position);
}
}
然后你應該添加一個setCallback方法並從activity / fragment中調用它。 此外,您不應該使回調靜態(當您在許多類中使用相同的適配器時,它可能會導致問題)。 您應該在ViewHolder中創建一個字段。 所以:
public MyAdapter(Context context, int resource, List<Item> items, Callback callback) {
super();
this.resource = resource;
this.items = items;
this.inflater = LayoutInflater.from(context);
this.callback = callback;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final ViewHolder viewHolder = (ViewHolder) holder;
final Item item = this.items.get(position);
viewHolder.caption.setText(item.caption);
viewHolder.callback = callback;
}
// A method to set a callback from activity/fragment.
public void setCallback(Callback callback) {
this.callback = callback;
}
public static class Item {
public long id;
public String number;
public String caption;
...
}
private static class ViewHolder extends RecyclerView.ViewHolder {
protected final TextView caption;
// A reference to an adapter's callback.
protected Callback callback;
public ViewHolder(View view) {
super(view);
this.caption = (TextView) view.findViewById(R.id.caption);
}
private View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.image) {
// Invoke the callback here.
if (callback != null) {
callback.onImageClick(getLayoutPosition());
}
}
}
};
}
}
制作適配器后,您可以調用它:
adapter = new MyAdapter(getActivity(), R.layout.item,
new ArrayList<MyAdapter.Item>(), null);
adapterListener = new MyAdapter.Callback() {
@Override
public void onImageClick(int position) {
// Some actions.
}
@Override
public void onRemoveItem(int position) {
// Some actions.
}
};
adapter.setCallback(adapterListener);
您可以將MainActivity作為Adapter的構造函數參數傳遞,並將其存儲在字段中。 或者你使用事件總線 - 有多種方法可以做到 - 我會去現場
在適配器中,創建一個接口,該接口將提供對主活動的回調
public interface MyCallback{
void onItemClicked();
}
private MyCallback listener;
public setOnItemClickListener(MyCallback callback){
listener = callback;
}
讓您的主要活動實現它。
public class MainActivity extends AppCompatActivity implements MyCallback
然后實現回調
@Override
public void onItemClick(){
//do work
}
然后只需從適配器設置回調
mDeviceListAdapter.setOnItemClickListener(this);
您可以使用Activity這樣的實例調用Activity方法,在MainActivity中編寫下面的代碼
mDeviceListAdapter = new DeviceListAdapter(MainActivity.this);
內部適配器
private MainActivity _mainActivity;
public DeviceListAdapter(MainActivity activity){
this._mainActivity=activity;
}
在你的onClick方法中
_mainActivity.yourActivityMethod(address);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.