gpt4 book ai didi

android - 为什么 Android 会在我的 SpinnerAdapter 中回收错误的 View 类型?

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:03:58 26 4
gpt4 key购买 nike

我正在尝试制作一个带有分隔符的 ActionBar 微调器。我实现了一个 SpinnerAdapter,它有 2 个项目 View 类型(感谢 getViewTypeCount)。问题是我从其他类型发送了一些 convertViews

这是我的 SpinnerAdapter:

public abstract class SeparatorSpinnerAdapter implements SpinnerAdapter {
Context mContext;
List<Object> mData;
int mSeparatorLayoutResId, mActionBarItemLayoutResId, mDropDownItemLayoutResId, mTextViewResId;

public static class SpinnerSeparator {
public int separatorTextResId;

public SpinnerSeparator(final int resId) {
separatorTextResId = resId;
}
}

public abstract String getText(int position);

public SeparatorSpinnerAdapter(final Context ctx, final List<Object> data, final int separatorLayoutResId, final int actionBarItemLayoutResId,
final int dropDownItemLayoutResId, final int textViewResId) {
mContext = ctx;
mData = data;
mSeparatorLayoutResId = separatorLayoutResId;
mActionBarItemLayoutResId = actionBarItemLayoutResId;
mDropDownItemLayoutResId = dropDownItemLayoutResId;
mTextViewResId = textViewResId;
}

protected String getString(final int resId) {
return mContext.getString(resId);
}

@Override
public void registerDataSetObserver(final DataSetObserver observer) {
}

@Override
public void unregisterDataSetObserver(final DataSetObserver observer) {
}

@Override
public int getCount() {
if (mData != null) {
return mData.size();
}
return 0;
}

@Override
public Object getItem(final int position) {
return mData == null ? null : mData.get(position);
}

@Override
public boolean isEmpty() {
return getCount() == 0;
}

@Override
public long getItemId(final int position) {
return 0;
}

@Override
public boolean hasStableIds() {
return false;
}

@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
return getView(mActionBarItemLayoutResId, position, convertView, parent);
}

public boolean isSeparator(final int position) {
final Object item = getItem(position);
if (item != null) {
return item instanceof SpinnerSeparator;
}
return false;
}

@Override
public int getItemViewType(final int position) {
return isSeparator(position) ? 0 : 1;
}

@Override
public int getViewTypeCount() {
return 2;
}

@Override
public View getDropDownView(final int position, final View convertView, final ViewGroup parent) {
return getView(isSeparator(position) ? mSeparatorLayoutResId : mDropDownItemLayoutResId, position, convertView, parent);
}

private View getView(final int layoutResId, final int position, final View convertView, final ViewGroup parent) {
View v;

Log.i("TAG", "getView #" + position + "\tVT=" + getItemViewType(position) + "\tCV="
+ (convertView == null ? " null " : convertView.getClass().getSimpleName()) + "\ttext=> " + getText(position));

if (convertView == null) {
final LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = li.inflate(layoutResId, parent, false);
} else {
v = convertView;
}

final TextView tv = (TextView) v.findViewById(mTextViewResId);
if (tv != null) {
tv.setText(getText(position));

if (isSeparator(position)) {
tv.setOnClickListener(null);
tv.setOnTouchListener(null);
}
}

return v;
}
}

一个实现:

public class IssuesMainFilterAdapter extends SeparatorSpinnerAdapter {
public IssuesMainFilterAdapter(final Context ctx, final List<Query> queries, final List<Project> projects) {
super(ctx, buildDataArray(queries, projects), R.layout.issues_filter_spinner_separator, R.layout.issues_filter_spinner_in_actionbar,
R.layout.issues_filter_spinner, R.id.issues_filter_spinner_text);
}

private static List<Object> buildDataArray(final List<Query> queries, final List<Project> projects) {
final List<Object> data = new ArrayList<Object>();
data.add(null); // "ALL"
data.add(new SpinnerSeparator(R.string.issue_filter_queries));
data.addAll(queries);
data.add(new SpinnerSeparator(R.string.issue_filter_projects));
data.addAll(projects);
return data;
}

@Override
public String getText(final int position) {
final Object item = getItem(position);
if (item == null) {
return getString(R.string.issue_filter_all);
} else if (item instanceof Query) {
return ((Query) item).name;
} else if (item instanceof Project) {
return ((Project) item).name;
} else if (item instanceof SpinnerSeparator) {
return getString(((SpinnerSeparator) item).separatorTextResId);
}
throw new InvalidParameterException("Item has unknown type: " + item);
}
}

您可能已经注意到,我在 getView() 中设置了一个日志行,以便我更好地理解正在发生的事情:

05-06 14:01:28.721 I/TAG( 5879): getView #0 VT=1    CV=TextView text=> ####
05-06 14:01:28.721 I/TAG( 5879): getView #1 VT=0 CV=LinearLayout text=> ####
05-06 14:01:28.729 I/TAG( 5879): getView #2 VT=1 CV=TextView text=> ####
05-06 14:01:28.745 I/TAG( 5879): getView #3 VT=1 CV=TextView text=> ####
05-06 14:01:28.745 I/TAG( 5879): getView #4 VT=0 CV=LinearLayout text=> ####
05-06 14:01:28.745 I/TAG( 5879): getView #5 VT=1 CV=TextView text=> ####
05-06 14:01:28.753 I/TAG( 5879): getView #6 VT=1 CV=TextView text=> ####
05-06 14:01:28.768 I/TAG( 5879): getView #7 VT=1 CV=TextView text=> ####
05-06 14:01:28.768 I/TAG( 5879): getView #8 VT=1 CV=TextView text=> ####
05-06 14:01:28.768 I/TAG( 5879): getView #9 VT=1 CV=TextView text=> ####
05-06 14:01:28.776 I/TAG( 5879): getView #10 VT=1 CV=TextView text=> ####
05-06 14:01:28.792 I/TAG( 5879): getView #11 VT=1 CV=TextView text=> ####
05-06 14:01:32.081 I/TAG( 5879): getView #12 VT=1 CV=TextView text=> ####
05-06 14:01:34.690 I/TAG( 5879): getView #13 VT=1 CV=LinearLayout text=> ####
05-06 14:01:35.573 I/TAG( 5879): getView #14 VT=1 CV=TextView text=> ####
05-06 14:01:37.237 I/TAG( 5879): getView #15 VT=1 CV=TextView text=> ####

您可能已经了解,我的实际项目布局是 TextView,分隔符布局是 LinearLayout。

如您所见,“真实”项目(日志中的 VT=1,请参阅项目 #13)正在回收分隔 View (CV=LinearLayout ).我原以为 Android 会提供相同类型的 convertView,因此只有在滚动时必须创建相同类型的 View (即另一个分隔符)时,才会回收第一个分隔符。

最佳答案

正如 David 发现的那样,这与 Android 框架有关。如前所述here , 框架不期望 Spinner 有不同的 View 类型。

这是我用来让我的 SpinnerAdapter 按我的意愿工作的解决方法:

  • 将 View 类型存储在 View 的标签中;
  • 如果没有要转换的 View 如果当前 View 类型与要转换的 View 不同,则扩充新布局。

这是我的自定义 getView 方法的代码:

private View getView(final int layoutResId, final int position, final View convertView, final ViewGroup parent) {
View v;

if (convertView == null || (Integer)convertView.getTag() != getItemViewType(position)) {
final LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = li.inflate(layoutResId, parent, false);
} else {
v = convertView;
}

v.setTag(Integer.valueOf(getItemViewType(position)));

final TextView tv = (TextView) v.findViewById(mTextViewResId);
if (tv != null) {
tv.setText(getText(position));

if (isSeparator(position)) {
tv.setOnClickListener(null);
tv.setOnTouchListener(null);
}
}

return v;
}

关于android - 为什么 Android 会在我的 SpinnerAdapter 中回收错误的 View 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16398468/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com