我正在尝试在我的应用中实现搜索功能,用户可以在其中搜索不同类型的数据:曲目,专辑或艺术家 . 用户选择他们将在活动A中搜索的数据类型,然后在活动B中执行实际搜索 .
在活动A中:
Intent intent = new Intent(this, PostSearch.class);
intent.putExtra(PostSearch.EXTRA_POST_TYPE, postType);
startActivityForResult(intent, RC_NEW_POST);
EXTRA_POST_TYPE
指定将要执行的搜索类型 . 然后在活动B中提取此额外内容 . 我已经为每种数据类型定义了类: Track
, Album
和 Artist
. 在活动B中,我有一个由适配器支持的 RecyclerView
. 我希望为每种数据类型使用相同的适配器定义 . 但是,我不确定这是否可行 .
我已将我的适配器定义如下(为简洁起见缩短):
public class PostSearchAdapter extends RecyclerView.Adapter<PostSearchAdapter.PostSearchViewHolder> {
private Context mContext;
private int mSearchType;
private List<?> mSearchResults;
public PostSearchAdapter(Context context, int searchType) {
this.mContext = context;
mSearchType = searchType;
switch (mSearchType) {
case 0:
mSearchResults = new ArrayList<Track>();
break;
case 1:
mSearchResults = new ArrayList<Album>();
break;
case 2:
mSearchResults = new ArrayList<Album>();
break;
default:
Log.i(TAG, "Invalid search type for adapter. Uh oh...");
break;
}
}
@Override
public int getItemCount() {
if (mSearchResults == null) {
return 0;
} else {
return mSearchResults.size();
}
}
@NonNull
@Override
public PostSearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View searchResult = LayoutInflater
.from(parent.getContext())
.inflate(R.layout.list_item_search_result, parent, false);
return new PostSearchViewHolder(searchResult);
}
@Override
public void onBindViewHolder(PostSearchViewHolder viewHolder, int position) {
switch (mSearchType) {
case 0:
Track track = (Track) mSearchResults.get(position);
viewHolder.mTitle.setText(track.getTitle());
viewHolder.mArtist.setText(track.getArtistNames());
if (!TextUtils.isEmpty(track.getAlbum().getLargeAlbumCover())) {
Picasso.get()
.load(track.getAlbum().getLargeAlbumCover())
.error(R.drawable.ic_no_cover)
.into(viewHolder.mCover);
}
break;
case 1:
// Handle album results here
break;
case 2:
// Handle artist results here
break;
default:
break;
}
}
public void addData(List<?> newData) {
mSearchResults.add(newData);
notifyDataSetChanged();
}
public void clearData(){
mSearchResults.clear();
}
}
我_243436_与 EXTRA_POST_TYPE
打交道并且可以做类似的事情:
mAdapter = new PostSearchAdapter(this, mSearchType);
...其中 mSearchType
具有 EXTRA_POST_TYPE
存储的值 . 但是,我的问题现在必须在我的适配器中处理 mSearchResults
. 我使用Java ?
通配符类型定义了这个成员变量:
private List<?> mSearchResults;
在知道适配器实例化之前,我知道列表将包含哪种类型的数据 . 然后我在适配器的overriden构造函数中实例化 mSearchResults
,因为我现在知道基于 mSearchType
的值放入数组的数据类型:
public PostSearchAdapter(Context context, int searchType) {
this.mContext = context;
mSearchType = searchType;
switch (mSearchType) {
//Instantiate mSearchResults here
}
}
有's 2 big issues that I'米面对这个 . 第一个是我仍然必须为 onBindViewHolder()
中列表中存储的对象进行强制转换:
Track track = (Track) mSearchResults.get(position);
我知道这是一个问题,因为使用参数化数据类型的一个主要优点是我们不再需要像上面那样进行构建 . 其次,我在 addData()
内仍然遇到编译时错误 . Android Studio通过捕获和通配符来抱怨:
我不完全理解错误,这让我处于停滞状态 .
我应该提一下,我对Java中的泛型没有最全面的理解,但我觉得我试图解决的问题可以通过使用它们来完成 . 任何形式的洞察力将不胜感激!
2 回答
EDIT
甚至不添加1乘1的元素也行 . 原因在 the 2 links I attached 中详细解释,检查出来 . 这也不起作用:
因为类型可能不一样 . 甚至没有从同一列表中获取元素:
我以为使用
addAll
方法会起作用 . 但它显示了同样的错误 .如果它正常工作,这编译,不知道:
在深入挖掘后,我发现this和this可能有助于我们更好地理解 .
你没有正确使用泛型 .
你的
Track
和Album
共享一个超类或任何接口吗?如果没有创建接口并将其添加到两个类,否则继续使用您的超类:
然后将您的适配器更改为
abstract
类,同时为ViewHolder
添加正确的类型声明和模板:这涉及基本方法 . 现在,您需要为每个搜索结果类型创建此适配器的子类(请注意,在extends中使用了type参数):
现在,只留下你的创造 . 简单的静态工厂方法将替代它,例如添加到
PostSearchAdapter
类:这使您可以通过简单的调用获得适当类型的适配器: