由于您想调度到您的活动,我建议您在活动中公开一个方法并直接从您的点击侦听器中调用它。最短的(在我看来也是最干净的):
-
在您的适配器中,例如 ArrayAdapter
- 定义为监听点击(以避免大量匿名监听器实例)
- 直接向您的 Activity 发送调用(因为每个视图上下文都是一个 Activity)
-
上面的context 可以被视为您的ApplicationActivity 仅如果您没有手动提供一些其他上下文,比如应用程序上下文
private final MyAdapter extends ArrayAdapter implements View.OnClickListener {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// inflate your card then get a reference to your button
View card = ....;
card.findViewById(R.id.YOUR_BUTTON_ID).setOnClickListener(this);
return card;
}
@Override
public void onClick(View view) {
ApplicationActivity activity = (ApplicationActivity) view.getContext();
if (activity != null && !activity.isFinishing()) {
applicationActivity.onCardButtonClick();
}
}
}
// in your ApplicationActivity
public final class ApplicationActivity extends Activity {
...
public void onCardButtonClick() {
// deal with your click
}
}
还有其他 textbook 选项(设置监听器,或在您的视图创建中进行活动等等),但我避免使用它们,因为它们绝对不能解决任何问题。
他们只是在你的代码中添加了更多的灰尘。
任何正确定义的View 上下文都指向包含所有视图结构的活动(因为它也是一个上下文)。通过这种方式,您可以快速且相对轻松地访问您的活动。
顺便说一句,事件总线不是一个好的选择,因为事件总线非常适合一对多关系(一个调度程序,多个侦听器),但在集中用于一对一调用时会增加更多复杂性(调度程序侦听器)
评论补充
您可以稍微调整一下代码,而不是使用适配器,您可以直接从您的单元中调度。换句话说,与其将适配器用作委托,不如创建一个匿名侦听器,然后直接通过您的卡片按钮点击访问并调用活动:
public final MyAdapter extends ArrayAdapter {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// inflate your card then get a reference to your button
View card = ....;
card.findViewById(R.id.YOUR_BUTTON_ID).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ApplicationActivity activity = (ApplicationActivity) view.getContext();
if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) {
applicationActivity.onCardButtonClick();
}
}
});
return card;
}
}
添加评论 - 复合视图
要封装所有单元格逻辑,您可以从头开始创建自定义视图或使用compound view。下面的例子是使用复合视图:
public class ApplicationActivity extends Activity {
....
public void onCardButtonClick(Cell cell) {
// do whatever you want with the model/view
}
}
// ViewModel instances are used in your adapter
public final class ViewModel {
public final String description;
public final String title;
public ViewModel(String title, String description) {
this.title = title != null ? title.trim() : "";
this.description = description != null ? description.trim() : "";
}
}
public final class Cell extends LinearLayout {
private View button;
private ViewModel model;
// ViewModel is data model and is the list of items in your adapter
public void update(ViewModel model) {
this.model = model;
// update your card with your model
}
public ViewModel getModel() {
return model;
}
@Override
protected void onAttachedToWindow() {
button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener {
@Override
public void onClick(View view) {
ApplicationActivity activity = (ApplicationActivity) view.getContext();
if (model != null && activity != null && !activity.isFinishing() && !activity.isDestroyed() {
activity.onCardButtonClick(Cell.this);
}
}
});
}
}
// then your adapter `getView()` needs to inflate/create your compound view and return it
public final MyAdapter extends ArrayAdapter {
private final List<ViewModel> items;
public MyAdapter() {
// update your models from outside or create on the fly, etc.
this.items = ...;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
// inflate - say it is a layout file 'cell.xml'
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.cell);
}
((Cell) convertView).update(items.get(position));
return convertView;
}
}