2014-03-13 24 views
2

我有一個包含ViewPager和其他更簡單視圖的佈局。我使用這個佈局作爲ListView的列表項,它工作正常。但是當我嘗試實現一個ViewHolder模式時,當我向下滾動時,應用程序崩潰。當我將適配器設置爲視圖分頁器時發生錯誤。在包含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; 

    } 
} 

編輯

堆棧跟蹤的錯誤我有我的執行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

確實需要這個視圖持有者模式嗎?你有多少物品? – pskink

+0

我有多達10個視圖,爲簡潔起見,此處省略。 –

+1

你能發佈異常堆棧跟蹤嗎? – curtisLoew

回答

2

在嘗試了一些替代方法後,像Horizo​​ntalScrollView或者一些外部庫,我仍然回到了從一開始就實現它的方式。我通過直接擴展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。

0

閱讀您發佈的堆棧跟蹤:

android.content.res.Resources$NotFoundException: Unable to find resource ID #0x3fe1 

似乎是你引用一個不存在的ID。這會導致您的應用崩潰,而不是持有者模式。

+0

我如何解釋我引用了一個不存在的ID? –

+0

爲什麼我沒有ViewHolder時出現同樣的錯誤呢? –

+0

你介意解釋downvote嗎? 我相信你的第一條評論的答案從我的回答中清晰可見。您似乎缺少持有者版本中的setId()方法,這可能解釋了爲什麼無法找到資源。 – curtisLoew

相關問題