我有一个布局,其中包括一个ViewPager,其他更简单的视图。我使用此布局作为ListView的列表项,它工作正常。但是当我尝试实现ViewHolder模式时,应用程序在向下滚动时崩溃。将适配器设置为视图寻呼机时发生错误。
适配器没有 ViewHolder实现:
public class FaceInSandAdapter extends ArrayAdapter<Gem> {
private Context mContext;
public FaceInSandAdapter(Context c, ArrayList<Gem> gems) {
super(c, 0, gems);
mContext = c;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final Gem gem = getItem(position);
convertView = ((Activity) mContext).getLayoutInflater().inflate(
R.layout.list_item_gem, null);
final ViewPager pager = (ViewPager) convertView
.findViewById(R.id.list_item_gem_photosViewPager);
pager.setId(gem.getId());
pager.setAdapter(new PhotoSliderPagerAdapter(((FragmentActivity) parent
.getContext()).getSupportFragmentManager(), gem.getImageUrls()));
TextView address = (TextView) convertView
.findViewById(R.id.list_item_gem_addressTextView);
address.setText(gem.getAddress());
return convertView;
}
}
如何为扩展包含ViewPager的布局的适配器正确实现ViewHolder模式?以下是我尝试实现这样的适配器,它给出了上面提到的错误:
public class FaceInSandAdapter extends ArrayAdapter<Gem> {
private Context mContext;
public FaceInSandAdapter(Context c, ArrayList<Gem> gems) {
super(c, 0, ads);
mContext = c;
}
static class ViewHolder {
ViewPager pager;
TextView address;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
final Gem gem = getItem(position);
if (convertView == null) {
convertView = ((Activity) mContext).getLayoutInflater().inflate(
R.layout.list_item_gem, null);
holder = new ViewHolder();
holder.pager = (ViewPager) convertView
.findViewById(R.id.list_item_gem_photosViewPager);
holder.address = (TextView) convertView
.findViewById(R.id.list_item_gem_addressTextView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
FragmentManager fm = ((FragmentActivity) convertView.getContext())
.getSupportFragmentManager();
holder.pager.setId(gem.getId());
holder.pager.setAdapter(new PhotoSliderPagerAdapter(fm, gem
.getImageUrls()));
holder.address.setText(gem.getAddress());
return convertView;
}
}
修改
Stacktrace用于我实现ViewHolder模式的错误:
FATAL EXCEPTION: main
Process: xx.yyy.zzzzzz, PID: 5010
android.content.res.Resources$NotFoundException: Unable to find resource ID #0x3fe1
at android.content.res.Resources.getResourceName(Resources.java:1776)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:919)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:472)
at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:163)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1068)
at android.support.v4.view.ViewPager.populate(ViewPager.java:914)
at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:442)
at xxx.xxx.xxx.FaceInSandAdapter.getView(FaceInSandAdapter.java:89)
at android.widget.AbsListView.obtainView(AbsListView.java:2240)
at android.widget.ListView.makeAndAddView(ListView.java:1790)
at android.widget.ListView.fillDown(ListView.java:691)
at android.widget.ListView.fillGap(ListView.java:655)
at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5136)
at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:4247)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
at android.view.Choreographer.doCallbacks(Choreographer.java:574)
at android.view.Choreographer.doFrame(Choreographer.java:543)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5102)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
**编辑2 **
现在,由于viepager正在作为listview项工作,剩下的问题是我实例化ImageViews,有一个简单的PagerAdapter实现(没有保存状态,没有限制屏幕外视图),所以列表最终使用大量内存。
答案 0 :(得分:2)
在尝试了一些替代方案之后,比如HorizontalScrollView或一些外部库,我仍然回过头来从一开始就实现这一点。我通过直接扩展PagerAdapter而不是FragmentStatePagerAdapter并覆盖instantiateItem
来解决这个问题。问题在于使用片段,现在看起来很明显:使用FragmentStatePagerAdapter确实不需要,因为我只是想制作一个照片滑块,所以使用片段是不必要的。
以下是我的新PhotoPagerAdapter的代码:
public class PhotoPagerAdapter extends PagerAdapter {
private Context mContext;
private List<String> mUrls;
public PhotoPagerAdapter(Context context, List<String> urls) {
mContext = context;
mUrls = urls;
}
@Override
public int getCount() {
return mUrls.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == ((RelativeLayout) object);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imgDisplay;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.fragment_gem_photo, container, false);
imgDisplay = (ImageView) v
.findViewById(R.id.fragment_gem_photo_imageView);
Picasso.with(mContext).load(mUrls.get(position))
.placeholder(R.drawable.wait_image).into(imgDisplay);
((ViewPager) container).addView(v);
return v;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((RelativeLayout) object);
}
}
修改强>
我发现问题不在于ViewHolder模式的错误实现。相反,当它包含一个带有FragmentStatePagerAdapter的viewpager时,重用已经膨胀的convertView。
答案 1 :(得分:0)
阅读您发布的堆栈跟踪:
android.content.res.Resources$NotFoundException: Unable to find resource ID #0x3fe1
您正在引用的ID似乎不存在。这会导致应用程序崩溃,而不是持有者模式。