29

Tôi có bộ điều hợp máy nhắn tin giả sử để thổi phồng một chế độ xem phức tạp đại diện cho một lịch.Làm cách nào để triển khai cơ chế tái chế chế độ xem cho PagerAdapter?

Mất khoảng 350 mili giây để thổi phồng mỗi năm của lịch.

Để cải thiện hiệu suất, tôi muốn triển khai cùng một cơ chế tồn tại trong bộ điều hợp mảng ListView của chế độ xem tái chế (convertView tham số trong getView()).

Đây là số getView() hiện tại của tôi từ bộ điều hợp.

@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; 
} 

Bất kỳ con trỏ hoặc hướng nào để thực hiện hành vi như vậy? Cụ thể như thế nào tôi có thể biết trong bộ điều hợp mà một trong số DateTileGridViews đang được vuốt màn hình để tôi có thể lưu nó vào bộ nhớ để tái sử dụng nó vào lần sau.

Trả lời

31

Vì vậy, tôi đã tìm ra.

  1. ghi đè destroyItem(ViewGroup container, int position, Object view) ans giúp bạn tiết kiệm cache xem
  2. tạo ra một phương pháp riêng biệt để xem nếu có bất kỳ cơ hội sử dụng một cái nhìn tái chế hoặc bạn nên thổi phồng một hình mới.
  3. hãy nhớ xóa chế độ xem được tái chế khỏi bộ nhớ cache sau khi được sử dụng để tránh có cùng một chế độ xem có cùng chế độ xem với máy nhắn tin.

đây là mã .. Tôi sử dụng một Stack xem để bộ nhớ cache tất cả các quan điểm gỡ bỏ khỏi máy nhắn tin của tôi

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()); 
} 

đừng quên để nhanh chóng ngăn xếp trong constructor adapter.

+0

Cảm ơn bạn rất nhiều! – penguin86

3

tôi đã làm như thế này ..đầu tiên tạo abstract class 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; 
    } 

nay kế thừa từ SoftCache vì vậy chúng tôi có thể thực hiện phương pháp 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); 
      } 
     } 

sau đó trong constructor của bạn nhanh chóng nó như thế này nếu bạn muốn nó được cho một lớp View ví dụ (nhưng nó có thể làm việc cho bất kỳ loại lớp):

SoftCache<View> myViewCache = new ViewCache(View.class); 

bây giờ trong destroyItem lưu chế độ xem để bộ nhớ cache:

@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 


    } 

nay phương pháp instantiateItem tận dụng nó chỉ đơn giản như thế này:

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

} 

update: nếu bạn muốn sử dụng bộ nhớ cache cho bố trí khác nhau hoặc không muốn mở rộng nó tôi đã đưa ra một giải pháp mà bạn có thể sử dụng bộ nhớ cache tương tự cho nhiều bố trí nơi bạn sẽ lấy lại bố trí bạn đặt trong việc sử dụng bố trí ID:

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

Một chút thay đổi trong SoftViewCache.get (int id) thay thế SoftReference softRef = multiMap.get (id) .get (0); với SoftReference softRef = multiMap.remove (id) .get (0); để xóa khỏi bộ nhớ cache vì nó không còn khả dụng để sử dụng lại. –

2

tôi giải quyết điều này bằng cách xác định một RecycleCache, như

này
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; 
    } 
} 

Kiểm tra mẫu mã của tôi ở đây RecyclerPagerAdapter

+0

Hoàn hảo, cảm ơn bạn! – georgehardcore

+0

Đây thực sự là một thư viện rất tốt. Nhưng nó không phải là mã giống như ở đây. Làm thế nào mà? –

+0

Mã đã có một số cải tiến sau khi đăng tại đây. –

Các vấn đề liên quan