更新:不再出现错误!现在请评论模式本身。优点和缺点。你喜欢什么,不喜欢什么。什么可以固定。仍然不明白我为什么这样做......让我知道(但请阅读下面的帖子)
我一直致力于在 Android 中为 BaseAdapters 创建一个新的设计模式,到目前为止,我真的很喜欢它的结果!
我有一个数据结构,可以为特定类型的集合中的每个实体保存所有需要的数据。我正在创建具有自己的 UI 布局的特定 BaseAdapter 实现,以便在屏幕上显示给用户。非常基本的好主意……没什么新鲜的。
好的,那我为什么要这个?
这样做的总体思路是:1) 抽象出 getView 方法的实现,让更多的业余开发人员更轻松地创建他们自己的自定义适配器,以及 2) 尽可能简化和抽象出更多细节。
注意:在最后 2 段代码中,我只有 3 件事要实现(这更有意义)。当前使用的 Holder 模式中存在的内部类、SetLayoutResource(...) 方法和 ExtractLayoutResources(...) 方法。
我想要这个并且认为它很好的 3 个关键原因是......抽象,抽象,抽象!
具体自定义适配器.java
(具体的示例代码...这基本上就是所有的样子!!!这基本上就是您创建新的 Custom BaseAdapter 所需要输入的所有内容!!!)
public class ConcreteCustomAdapter extends BaseDataAdapter<Song, SongHolder> {
public ConcreteCustomAdapter(Context context, int resource, Song[] data) {
super(context, resource, data);
// Give the base class a reference to the actual type of Holder class to use
this.setViewHolder(new SongHolder());
}
@Override
protected void setLayoutResources(SongHolder holder, Song data) {
// Set the View Holder objects properties with the current data
holder.imgUiControl.setImageResource(data.thumbnail);
holder.txtUiControl.setText(data.Name);
}
@Override
protected void extractLayoutResources(View row, SongHolder holder) {
// Convert XML UI component definitions into the static View Holder object
holder.imgUiControl = (ImageView) row.findViewById(R.id.imgUiControl);
holder.txtUiControl = (TextView) row.findViewById(R.id.txtUiControl);
}
// Class that holds all the UI component references
static class SongHolder implements IHolder {
ImageView imgUiControl;
TextView txtUiControl;
}
}
Song.java
(用户已创建!)
// Entity that holds ALL the data
public class Song implements IData {
public int thumbnail;
public String Name;
...
// Constructors, Getters, Setters
...
}
代码的其余部分用于支持目的
IHolder.java
// Current Adapter Pattern uses Holder Objects, this represents that and the data via interface
public interface IHolder {
interface IData { }
}
基础数据适配器.java
(用户不应触摸此)
// D for Data....H for Holder (sorry not convention)
public abstract class BaseDataAdapter<D extends IData, H extends IHolder> extends BaseAdapter {
private Context context;
private int layoutResourceID;
private D data[] = null;
private H holder = null;
public BaseDataAdapter(Context context, int resource, D[] data) {
//super(context, resource, data);
this.layoutResourceID = resource;
this.context = context;
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//super.getView(position, convertView, parent);
View row = convertView;
if (row == null) {
LayoutInflater newView = ((Activity) context).getLayoutInflater();
row = newView.inflate(this.layoutResourceID, parent, false);
extractLayoutResources(row, holder);
row.setTag(holder);
} else {
holder = (H) row.getTag();
}
setLayoutResources(holder, data[position]);
return row;
}
public void setViewHolder(H holder) {
this.holder = holder;
}
abstract protected void setLayoutResources(H holder, D data);
abstract protected void extractLayoutResources(View row, H holder);
@Override
public int getCount() { return this.data.length; }
@Override
public Object getItem(int position) { return this.data[position]; }
@Override
public long getItemId(int position) { return 0; }
}
最佳答案
我会这样做:
public abstract class TypedListAdapter<T, H extends TypedListAdapter.ViewHolder> extends BaseAdapter {
private final int itemViewId;
private List<T> data;
public TypedAdapter(final int itemViewId) {
this(itemViewId, null);
}
public TypedAdapter(final int itemViewId, final List<T> data) {
this.itemViewId = itemViewId;
this.data = preventNull(data);
}
private List<T> preventNull(final List<T> data) {
return data == null ? Collections.<T>emptyList() : data;
}
public void setData(final List<T> data) {
final List<T> nonNullData = preventNull(data);
if (nonNullData != this.data) {
this.data = nonNullData;
notifyDataSetChanged();
}
}
@Override
public int getCount() {
return data.size();
}
@Override
public T getItem(final int position) {
return data.get(position);
}
@Override
public long getItemId(final int position) {
return position;
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final H holder = obtainHolder(convertView, parent);
bind(holder, getItem(position));
return holder.view;
}
protected abstract void bind(final H holder, final T item);
private H obtainHolder(final View convertView, final ViewGroup parent) {
if (convertView == null) {
final View view = LayoutInflater.from(parent.getContext()).inflate(itemViewId, parent, false);
return createHolder(view);
} else {
return (H) convertView.getTag();
}
}
protected abstract H createHolder(final View view);
public static class ViewHolder {
public final View view;
public ViewHolder(final View view) {
this.view = view;
view.setTag(this);
}
}
}
适配器的实现可能如下所示:
public class SongListAdapter extends TypedListAdapter<Song, SongListAdapter.SongHolder> {
public SongListAdapter(final int itemViewId) {
super(itemViewId);
}
public SongListAdapter(final int itemViewId, final List<Song> data) {
super(itemViewId, data);
}
@Override
protected void bind(final SongHolder holder, final Song item) {
holder.name.setText(item.getName());
holder.thumbnail.setImageResource(item.getThumbnail());
}
@Override
protected SongHolder createHolder(final View view) {
return new SongHolder(view);
}
public static class SongHolder extends ViewHolder {
public final ImageView thumbnail;
public final TextView name;
public SongHolder(final View view) {
super(view);
thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
name = (TextView) view.findViewById(R.id.name);
}
}
}
关于android - 在 Android 中设计新的 BaseAdapter 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19015440/