我尝试在我的应用中使用我的API来更新基于Google MapView位置的RecyclerView,因此这意味着API将返回不同大小的列表,并经常返回。
加载初始应用程序后,当我更改位置时,我会触发一个新的API调用,该调用会创建一个新的Adapter并调用RecyclerView.swapAdapter()
方法。
这似乎是一个非常简单的解决方案,但我无法在RecyclerView或RecyclerView.ViewHolder文档中找到解决此问题的任何内容。
问题在于:
这是我的基本代码结构:
在我的API类
中public void getFeed(final RecyclerView recView, final Location loc){
service().getFeed(MyFeeds.API_FEED).enqueue(new Callback<NearbyPeopleProto.NearbyPeopleFeed>() {
@Override
public void onResponse(Response<NearbyPeopleProto.NearbyPeopleFeed> response, Retrofit retrofit) {
Log.d(LOG_TAG, "recview Child count: " + recView.getChildCount());
ArrayList<NearbyPeople> near = new RtGtfsParser(c).getStopsByLocation(response.body(), loc);
/*Log.d(LOG_TAG, "onResponse: " + recView.getChildCount() + " -- " + near.get(0).getStops().size());
if(recView.getChildCount() > near.get(0).getStops().size()) {
//recView.removeViews(near.get(0).getStops().size() - 1, recView.getChildCount() - 1);
recView.removeViewAt(1);
Log.d(LOG_TAG, "onResponse: " + recView.getChildCount());
}*/
GroupListAdapter ta = new GroupListAdapter(c, near);
Log.d(LOG_TAG, "onResponse: Swapping");
//recView.setAdapter(ta);
recView.swapAdapter(ta, true);
}
@Override
public void onFailure(Throwable t) {
Log.e(LOG_TAG, t.getMessage());
}
});
}
我的适配器类
public class GroupListAdapter extends
RecyclerView.Adapter<GroupListAdapter.ViewHolder> {
ArrayList<NearbyPeople> NearbyPeople;
public GroupListAdapter(ArrayList<NearbyPeople> NearbyPeople) {
this.NearbyPeople = NearbyPeople;
}
@Override
public GroupListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View stationView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new ViewHolder(stationView);
}
@Override
public void onBindViewHolder(GroupListAdapter.ViewHolder vh, int position) {
if(NearbyPeople.get(0).getStops() != null) {
Log.d(LOG_TAG, "onBindViewHolder: " + NearbyPeople.get(0).getStops().size());
vh.locationTag.setText(NearbyPeople.get(0).getStops().get(position).stopName);
} else {
vh.locationTag.setText("Loading...");
}
}
@Override
public int getItemCount() {
return NearbyPeople.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView locationTag;
public ViewHolder(View itemView) {
super(itemView);
locationTag = (TextView) itemView.findViewById(R.id.location_tag);
}
}
}
LogCat输出:
01-12 22:36:27.718 6821-6821/net.mastrgamr.myapp D/TripActivity: onCameraChange:
//API gets called on the initial app load
01-12 22:36:28.597 6821-6821/net.mastrgamr.myapp I/System.out: LOADING MAP
01-12 22:36:28.622 6821-6831/net.mastrgamr.myapp W/art: Suspending all threads took: 9.511ms
01-12 22:36:28.633 6821-6831/net.mastrgamr.myapp I/art: Background sticky concurrent mark sweep GC freed 16785(866KB) AllocSpace objects, 9(3MB) LOS objects, 0% free, 68MB/68MB, paused 16.852ms total 67.527ms
01-12 22:36:28.635 6821-6821/net.mastrgamr.myapp D/TripActivity: onMyLocationChange: Location[fused 40.882174,-73.833406 acc=50 et=+2d19h35m3s487ms]
01-12 22:36:28.685 6821-6831/net.mastrgamr.myapp I/art: Background partial concurrent mark sweep GC freed 2960(217KB) AllocSpace objects, 28(26MB) LOS objects, 24% free, 48MB/64MB, paused 5.893ms total 47.174ms
01-12 22:36:28.903 6821-6821/net.mastrgamr.myapp D/ApiService: recview Child count: 1
01-12 22:36:28.906 6821-6821/net.mastrgamr.myapp D/NearbyGroups: mapping to model
01-12 22:36:28.913 6821-6821/net.mastrgamr.myapp I/System.out: MAPPED!!: [net.mastrgamr.tpulse.models.realtime.NearbyGroups$Stops@6ebd215, net.mastrgamr.tpulse.models.realtime.NearbyGroups$Stops@da9092a]
01-12 22:36:28.913 6821-6821/net.mastrgamr.myapp D/NearbyGroups: mapping to model
01-12 22:36:28.926 6821-6821/net.mastrgamr.myapp I/System.out: MAPPED!!: [net.mastrgamr.tpulse.models.realtime.NearbyGroups$Stops@23fe31b, net.mastrgamr.tpulse.models.realtime.NearbyGroups$Stops@e481cb8]
01-12 22:36:28.927 6821-6821/net.mastrgamr.myapp D/ApiService: onResponse: Swapping
01-12 22:36:28.943 6821-6821/net.mastrgamr.myapp D/GroupListAdpter: onBindViewHolder: 2
01-12 22:36:28.952 6821-6821/net.mastrgamr.myapp D/GroupListAdpter: onBindViewHolder: 2
01-12 22:36:29.996 6821-6821/net.mastrgamr.myapp D/TripActivity: onCameraChange:
01-12 22:36:33.397 6821-6821/net.mastrgamr.myapp D/TripActivity: onCameraChange:
//API also gets called when the map is moved.
01-12 22:36:33.399 6821-6821/net.mastrgamr.myapp D/TripActivity: CAMERA MOVED -- Regenerating: Location[Moved Location 40.880845,-73.837932 acc=??? t=?!? et=?!?]
01-12 22:36:33.749 6821-6821/net.mastrgamr.myapp D/ApiService: recview Child count: 2
01-12 22:36:33.749 6821-6821/net.mastrgamr.myapp D/NearbyGroups: mapping to model
01-12 22:36:33.755 6821-6821/net.mastrgamr.myapp I/System.out: MAPPED!!: [net.mastrgamr.tpulse.models.realtime.NearbyGroups$Stops@90eab4a]
01-12 22:36:33.755 6821-6821/net.mastrgamr.myapp D/NearbyGroups: mapping to model
01-12 22:36:33.762 6821-6821/net.mastrgamr.myapp I/System.out: MAPPED!!: [net.mastrgamr.tpulse.models.realtime.NearbyGroups$Stops@8abaabb]
01-12 22:36:33.763 6821-6821/net.mastrgamr.myapp D/ApiService: onResponse: Swapping
01-12 22:36:33.770 6821-6821/net.mastrgamr.myapp D/GroupListAdpter: onBindViewHolder: 1
01-12 22:36:33.772 6821-6821/net.mastrgamr.myapp D/GroupListAdpter: onBindViewHolder: 1
01-12 22:36:33.778 6821-6821/net.mastrgamr.myapp D/AndroidRuntime: Shutting down VM
01-12 22:36:33.995 6821-6821/net.mastrgamr.myapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: net.mastrgamr.myapp, PID: 6821
java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at net.mastrgamr.tpulse.adapters.GroupListAdpter.onBindViewHolder(GroupListAdpter.java:63)
at net.mastrgamr.tpulse.adapters.GroupListAdpter.onBindViewHolder(GroupListAdpter.java:25)
at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:5217)
at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:5250)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4487)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4363)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1961)
答案 0 :(得分:0)
Swap
之间的list
仅在大小相同的情况下有效,如果list
中的一个比其他swap
更短或更大,则String one = {"1","2"}
将无效预计,你得到一个假定的结果。
示例:String two = {"4","8","10"}
与two
交换。你知道会发生什么会在one
数组中丢弃最后一个元素,因为adapter
数组没有第3个元素。
虽然swapAdapter();没有显示文档,但您可以假设这是。
处理此问题的最佳和最快捷的方法是制作新的RecyclerView
并将其分配给zipWithIndex
。
答案 1 :(得分:0)
我发现了这个问题,这是一个基本的错误。如果您不了解我的适配器列表结构,可能很难错过。
我的适配器代码
-----
@Override
public void onBindViewHolder(GroupListAdapter.ViewHolder vh, int position) {
if(NearbyPeople.get(0).getStops() != null) {
// the line below accesses an inner array to get to the info i really want
vh.locationTag.setText(NearbyPeople.get(0).getStops().get(position).stopName);
} else {
vh.locationTag.setText("Loading...");
}
}
@Override
public int getItemCount() {
return NearbyPeople.size(); //Causing bug/runtime error. This only accesses the root 'node' of the array
}
-----
问题发生在getItemCount()
。我使用此适配器根据“根”数组中的2个内部数组之一显示信息。我只返回getItemCount()
中根数组的大小(仅为2)。
这就是为什么当我得到的API结果小于1时,我的应用程序会抛出RuntimeException,如果结果返回的数组大于2,它仍然只会在我的RecyclerView中显示2个元素。