在我的Android应用程序中,我认为我的目标非常简单 - 生成已安装应用程序的列表并在每个旁边放置一个勾选框,作为“勾选到排除”列表。
要生成已安装的应用程序列表,我使用标准的Android示例代码,在片段here中进行演示。我不会重新发布所有内容以使这篇文章尽可能简洁。
性能非常糟糕,关于此主题的第一个问题是请求示例代码,LazyLoads应用程序图标。在images are being downloaded时,将LazyLoading图标实现为ListView似乎只是一个问题。由于Android在生成应用程序列表时不使用此方法,因此我想知道这是否过度杀伤?
当检查CheckedTextView并且视图在列表中回收further boxes become ticked down the list(在初始视图中)or they 'forget' they have been ticked时,问题就开始了。
为了解决这个问题,我必须保留对已勾选项目的引用并使用getView()中的following code
// store CheckTextView's
private static HashMap<Integer, CheckedTextView> mCheckedList = new HashMap<Integer, CheckedTextView>();
// store state
private static HashMap<Integer, Boolean> mIsChecked = new HashMap<Integer, Boolean>();
@Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View view;
if (convertView == null) {
view = mInflater.inflate(R.layout.list_item_icon_text, parent, false);
} else {
view = convertView;
}
final AppEntry item = getItem(position);
((ImageView) view.findViewById(R.id.icon)).setImageDrawable(item.getIcon());
CheckedTextView ctv = (CheckedTextView) view.findViewById(R.id.text1);
ctv.setText(item.getLabel());
// set current state
if (mIsChecked.get(position) != null) {
if (mIsChecked.get(position)) {
ctv.setChecked(true);
}
} else {
ctv.setChecked(false);
}
ctv.setTag(position);
mCheckedList.put(position, ctv);
ctv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
CheckedTextView ct = mCheckedList.get(view.getTag());
if (DE.BUG) {
MyLog.d("ct text: " + ct.getText().toString());
}
ct.toggle();
mIsChecked.put((Integer) view.getTag(), ct.isChecked());
}
});
return view;
}
}
这很有效,但是由于为每个视图进行了刷新/回收所做的工作以及放置在每个项目上的OnClickListener(下面有更多内容),性能非常糟糕 - Eclipse还告诉我还有更多其他内容要改变:
使用新的SparseArray(...)代替更好 性能
我的困境并不止于此......为了帮助用户快速找到他们想要的应用程序,我实现了如下过滤器:
@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Place an action bar item for searching.
MenuItem item = menu.add("Search");
item.setIcon(android.R.drawable.ic_menu_search);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
View searchView = SearchViewCompat.newSearchView(getActivity());
if (searchView != null) {
SearchViewCompat.setOnQueryTextListener(searchView,
new OnQueryTextListenerCompat() {
@Override
public boolean onQueryTextChange(String newText) {
// Called when the action bar search text has changed. Since this
// is a simple array adapter, we can just have it do the filtering.
mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
mAdapter.getFilter().filter(mCurFilter);
return true;
}
});
item.setActionView(searchView);
}
}
我假设当输入过滤器时,重新绘制ListView并且对位置的引用变得混乱?这导致框根据它们在显示器上的位置而被勾选。
我必须为上面的每个条目实现一个OnClickListener,因为我无法从onListItemClick获得对CheckedTextView的引用。以下是我的一些尝试:
@Override
public void onListItemClick(final ListView listView, final View view, final int position, final long id) {
// View v = (View) listView.getChildAt(position);
// CheckedTextView ctv = (CheckedTextView)
// v.findViewById(R.id.text1);
// ctv.toggle();
// RelativeLayout r = (RelativeLayout) view;
// CheckedTextView ctv = (CheckedTextView)
// r.findViewById(R.id.text1);
// CheckedTextView ctv = (CheckedTextView) view;
// ((CheckedTextView)
// listView.getItemAtPosition(position)).setChecked(!((CheckedTextView)
// listView
// .getItemAtPosition(position)).isChecked());
// CheckedTextView ctv = (CheckedTextView) view.getTag(position);
// ctv.toggle();
作为@CommonsWare replied in this topic,对findViewById(R.id.text1)
的CheckedTextView引用不是我所追求的。
编辑 - XML布局
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
android:paddingRight="6dip" >
<CheckedTextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/icon"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:paddingLeft="4dip"
android:paddingTop="4dip"
android:textStyle="bold"
android:duplicateParentState="true" />
<ImageView
android:id="@+id/icon"
android:layout_width="48dip"
android:layout_height="48dip"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:paddingLeft="2dip" />
</RelativeLayout>
我准备放弃并使用单独的文本视图和复选框实现我自己的布局,但我不禁想到如果我这样做,我将重新发明轮子?我是否比应该做的更难!?
在理想的世界中:
我希望有人可以提供帮助,我提前感谢你。