29

मेरे पास एक पेजर एडाप्टर है जो एक कैलेंडर का प्रतिनिधित्व करने वाले जटिल दृश्य को बढ़ाने का अनुमान लगाता है।पेजर एडाप्टर के लिए दृश्य रीसाइक्लिंग तंत्र को मैं कैसे कार्यान्वित करूं?

कैलेंडर के प्रत्येक वर्ष को बढ़ाने के लिए लगभग 350 एमएस लगते हैं।

प्रदर्शन में सुधार करने के लिए मैं एक ही तंत्र है जो रीसाइक्लिंग विचारों का ListView सरणी अनुकूलक (getView() में convertView पैरामीटर) में मौजूद है को लागू करना चाहते हैं।

एडाप्टर से मेरा वर्तमान getView() यहां है।

@Override 
protected View getView(VerticalViewPager pager, final DateTileGrid currentDataItem, int position) 
{ 
    mInflater = LayoutInflater.from(pager.getContext()); 

     // This is were i would like to understand weather is should use a recycled view or create a new one. 
    View datesGridView = mInflater.inflate(R.layout.fragment_dates_grid_page, pager, false); 


    DateTileGridView datesGrid = (DateTileGridView) datesGridView.findViewById(R.id.datesGridMainGrid); 
    TextView yearTitle = (TextView) datesGridView.findViewById(R.id.datesGridYearTextView); 
    yearTitle.setText(currentDataItem.getCurrentYear() + ""); 
    DateTileView[] tiles = datesGrid.getTiles(); 

    for (int i = 0; i < 12; i++) 
    { 
     String pictureCount = currentDataItem.getTile(i).getPictureCount().toString(); 
     tiles[i].setCenterLabel(pictureCount); 
     final int finalI = i; 
     tiles[i].setOnCheckedChangeListener(new DateTileView.OnCheckedChangeListener() { 
      @Override 
      public void onCheckedChanged(DateTileView tileChecked, boolean isChecked) 
      { 
       DateTile tile = currentDataItem.getTile(finalI); 
       tile.isSelected(isChecked); 
      } 
     }); 
    } 

    return datesGridView; 
} 

ऐसे व्यवहार को लागू करने के लिए कोई संकेतक या दिशा? विशेष रूप से मैं एडाप्टर में कैसे जान सकता हूं कि DateTileGridViews में से एक को स्क्रीन से स्वाइप किया जा रहा है, इसलिए मैं इसे अगली बार पुन: उपयोग करने के लिए स्मृति में सहेज सकता हूं।

उत्तर

31

तो मैंने इसे समझ लिया है।

  1. destroyItem(ViewGroup container, int position, Object view) अधिलेखित ans आप दृश्य कैश्ड
  2. अगर वहाँ एक पुनर्नवीनीकरण दृश्य का उपयोग करने के लिए किसी भी मौका है या आप एक नया बढ़ चाहिए देखने के लिए एक अलग विधि बनाने, सहेजने।
  3. कैश से पुनर्नवीनीकरण दृश्य को हटाने के लिए याद रखें जब इसे एक ही दृश्य को पेजर पर एक ही दृश्य संलग्न करने से बचने के लिए उपयोग किया जाता है।

यहाँ कोड है .. मैं अपने पेजर से निकाले गए सभी विचारों को कैश करने के

private View inflateOrRecycleView(Context context) 
{ 

    View viewToReturn; 
    mInflater = LayoutInflater.from(context); 
    if (mRecycledViewsList.isEmpty()) 
    { 
     viewToReturn = mInflater.inflate(R.layout.fragment_dates_grid_page, null, false); 
    } 
    else 
    { 
     viewToReturn = mRecycledViewsList.pop(); 
     Log.i(TAG,"Restored recycled view from cache "+ viewToReturn.hashCode()); 
    } 


    return viewToReturn; 
} 

@Override 
public void destroyItem(ViewGroup container, int position, Object view) 
{ 
    VerticalViewPager pager = (VerticalViewPager) container; 
    View recycledView = (View) view; 
    pager.removeView(recycledView); 
    mRecycledViewsList.push(recycledView); 
    Log.i(TAG,"Stored view in cache "+ recycledView.hashCode()); 
} 

मत भूलना एडाप्टर निर्माता में ढेर का दृष्टांत को देखने के एक ढेर का इस्तेमाल किया।

+0

आपको बहुत बहुत धन्यवाद! – penguin86

3

मैंने इसे ऐसा किया ..पहले सार softCache वर्ग बनाने के लिए:

public abstract class SoftCache<T> { 
    private Stack<Reference<T>> mRecyclingStack; 
    final Class<T> classType; 

    public SoftCache(Class<T> typeParameterClass) { 
     this.classType = typeParameterClass; 
     mRecyclingStack = new Stack<Reference<T>>(); 
    } 

    /* implement this to create new object of type T if cache is empty */ 
    public abstract T runWhenCacheEmpty(); 

    /* 
    * retrieves last item from cache or creates a new T object if cache is 
    * empty 
    */ 
    public T get() { 
     T itemCached = null; 

     if (mRecyclingStack.isEmpty()) { 
      itemCached = runWhenCacheEmpty(); 

     } else { 
      SoftReference<T> softRef = (SoftReference<T>) mRecyclingStack 
        .pop(); 

      Object obj = softRef.get(); 
      /* 
      * if referent object is empty(due to GC) then create a new 
      * object 
      */ 
      if (obj == null) { 
       itemCached = runWhenCacheEmpty(); 

      } 
      /* 
      * otherwise restore from cache by casting the referent as the 
      * class Type that was passed to constructor 
      */ 
      else { 
       itemCached = (classType.cast(softRef.get())); 
      } 
     } 
     return itemCached; 
    } 

अब SoftCache से विरासत तो हम runWhenCacheEmpty विधि को लागू कर सकते हैं:

public class ViewCache extends SoftCache<View>{ 

      public ViewCache(Class<View> typeParameterClass) { 
       super(typeParameterClass); 
      } 

      @Override 
      public View runWhenCacheEmpty() { 
       return mFragment.getActivity().getLayoutInflater() 
         .inflate(R.layout.mypagelayout, null); 
      } 
     } 

फिर अपने निर्माता में इसे इस तरह का दृष्टांत यदि आप इसे एक दृश्य वर्ग के लिए होना चाहता हूँ

SoftCache<View> myViewCache = new ViewCache(View.class); 
destroyItem में

अब कैश करने के लिए दृश्य को बचाने: (उदाहरण के लिए, लेकिन यह वर्ग के किसी भी प्रकार के लिए काम कर सकते हैं)

+०१२३५१६४१०६
@Override 
    public void destroyItem(final ViewGroup container, final int position, final Object object) { 
     final View v = (View) object; 

     if(v.getId() == R.id.mypagelayout) 
      myViewCache.put(v); //this saves it 


    } 

अब विधि instantiateItem बस इस तरह यह का इस्तेमाल करते हैं:

@Override 
    public Object instantiateItem(final ViewGroup container, final int position) { 
     View MyPageView=myViewCache.get(); 

} 

अद्यतन: मैं एक समाधान के साथ आया था आप विभिन्न लेआउट के लिए कैश का उपयोग करना चाहते हैं या इसे विस्तार करने के लिए पसंद नहीं है, तो जहां

public class SoftViewCache { 

    private HashMap<Integer,ArrayList<SoftReference<View>>> multiMap; 

    public SoftViewCache() { 
     multiMap= new HashMap<Integer, ArrayList<SoftReference<View>>>();   
    } 

    /* 
    * retrieves cached item or return null if cache is 
    * empty 
    */ 
    public View get(int id) { 
     View itemCached = null; 
     if (!multiMap.containsKey(id)) { 
      return null; 
     } 
     else { 
      /*get the referent object and check if its already been GC if not we re-use*/ 
      SoftReference<View> softRef =multiMap.get(id).get(0); 
      Object obj = softRef.get(); 
      /* 
      * if referent object is empty(due to GC) then caller must create a new 
      * object 
      */ 
      if (null == obj) { 
       return null; 
      } 
      /* 
      * otherwise restore from cache 
      */ 
      else { 
       itemCached = (softRef.get()); 
      } 
     } 
     return itemCached; 
    } 

    /* saves a view object to the cache by reference, we use a multiMap to allow 
    * duplicate IDs*/ 
    public void put(View item) { 
     SoftReference<View> ref = new SoftReference<View>(item); 
     int key = item.getId(); 
      /*check if we already have a reuseable layouts saved if so just add to the list 
      * of reusable layouts*/ 
     if (multiMap.containsKey(key)) { 
      multiMap.get(key).add(ref); 
     } else { 
      /*otherwise we have no reusable layouts lets create a list of reusable layouts 
      * and add it to the multiMap*/ 
      ArrayList<SoftReference<View>> list = new ArrayList<SoftReference<View>>(); 
      list.add(ref); 
      multiMap.put(key, list); 
     } 
    } 
} 
+0

सॉफ़्टविच कैश.get (int id) में एक छोटा सा परिवर्तन सॉफ़्ट रेफरेंस softRef = multiMap.get (id) .get (0) को प्रतिस्थापित करता है; सॉफ़्ट रेफरेंस softRef = multiMap.remove (id) .get (0); कैश से निकालने के लिए क्योंकि यह अब पुन: उपयोग के लिए उपलब्ध नहीं है। –

2

मैं एक RecycleCache को परिभाषित करने, इस

तरह से इस हल: एक से अधिक लेआउट के लिए एक ही कैश जहां का उपयोग कर लेआउट आईडी में लेआउट डाल पुनः प्राप्त होगा उपयोग कर सकते हैं
protected static class RecycleCache { 

    private final RecyclerPagerAdapter mAdapter; 

    private final ViewGroup mParent; 

    private final int mViewType; 

    private List<ViewHolder> mCaches; 

    public RecycleCache(RecyclerPagerAdapter adapter, ViewGroup parent, int viewType) { 
    mAdapter = adapter; 
    mParent = parent; 
    mViewType = viewType; 
    mCaches = new ArrayList<>(); 
    } 

    public ViewHolder getFreeViewHolder() { 
    int i = 0; 
    ViewHolder viewHolder; 
    for (int n = mCaches.size(); i < n; i++) { 
     viewHolder = mCaches.get(i); 
     if (!viewHolder.mIsAttached) { 
     return viewHolder; 
     } 
    } 
    viewHolder = mAdapter.onCreateViewHolder(mParent, mViewType); 
    mCaches.add(viewHolder); 
    return viewHolder; 
    } 
} 

चेक बाहर मेरी नमूना कोड यहाँ RecyclerPagerAdapter

+0

बिल्कुल सही, धन्यवाद! – georgehardcore

+0

यह वास्तव में एक बहुत अच्छी पुस्तकालय है। लेकिन यह वही कोड नहीं है जैसा कि यहां है। कैसे? –

+0

कोड पोस्ट करने के बाद कोड में कुछ सुधार हुए थे। –

संबंधित मुद्दे