2016-03-07 140 views
0

如果我不得不發送請求以獲取onBindViewHolder()以內的數據,那麼在數據從服務器返回後,如何更新視圖?如何從服務器提取數據後更新recyclerview?

我現在所擁有的是我將數據與行位置一起緩存,以便下次用戶滾動到該行時,我可以立即顯示信息。

但還有2個其他問題我不知道如何解決。

  1. 我滾動列表查看位置10,11和12處的項目。我決定等待數據返回。之後我打電話notifyDataSetChanged()?因爲onBindViewHolder已經被數據返回的時間調用並且視圖將保持爲空,但是我也不認爲在每個請求都是好主意後調用notifyDataSetChanged()
  2. 我開始查看位置0處的列表,並保持滾動到位置10.應用程序發送請求以將位置0的數據提取爲10.由於0處的請求首先發送出去,所以它更有可能首先返回或至少比位置10快,但那時我已經在位置10查看該項目了。如果所有請求都返回,我的視圖將開始改變,所以它將顯示位置0的數據,然後一直保持更新10.

從服務器加載數據爲recyclerview卷軸是一種不好的做法嗎?但通過這樣做會爲我節省很多時間,我想也是爲了用戶?因爲不是提前發送所有請求,用戶可以看到部分數據,而其他數據正在後臺加載。

謝謝!

EDITED

public class TestAdapter extends RecyclerView.Adapter<TestAdapter.ViewHolder> { 
    private Context ctx; 
    private ArrayList<Photo> alPhotos = new ArrayList<>(); 
    private HashMap<String, Drawable> hmImages = new HashMap<>(); 

    public TestAdapter(Context ctx, ArrayList<Photo> alPhotos) { 
     this.ctx = ctx; 
     this.alPhotos = alPhotos; 
    } 

    @Override 
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_photo_brief, parent, false)); 
    } 

    @Override 
    public void onBindViewHolder(ViewHolder holder, int position) { 
     Photo photo = alPhotos.get(position); 

     loadRemoteImage(photo.IMG, holder.ivThumb, true); 
     holder.tvEmail.setText(photo.EMAIL); 
    } 

    @Override 
    public int getItemCount() { 
     return alPhotos.size(); 
    } 

    private void loadRemoteImage(final String imgUrl, final ImageView view, final boolean cache) { 
     if (hmImages.containsKey(imgUrl)) { 
      view.setImageDrawable(hmImages.get(imgUrl)); 
     } else { 
      final WeakReference<ImageView> weakView = new WeakReference<>(view); 
      RequestManager.getManager().add(new Request<>(imgUrl, new DrawableParser(), new RequestCallback<Drawable>() { 
         @Override 
         public void onFinished(Request<Drawable> request, Response<Drawable> response) { 
          if (cache) hmImages.put(imgUrl, response.result); 

          ImageView view = weakView.get(); 
          if (view != null) { 
           view.setImageDrawable(response.result); 
          } 
         } 

         @Override 
         public void onError(Request<Drawable> request, Response<Drawable> response) { 
         } 

         @Override 
         public void onTimeout(Request<Drawable> request, Response<Drawable> response) { 
         } 
        }) 
      ); 
     } 
    } 

    public class ViewHolder extends RecyclerView.ViewHolder { 
     private ImageView ivThumb; 
     private TextView tvEmail; 

     public ViewHolder(View itemView) { 
      super(itemView); 
      findViews(); 
     } 

     private void findViews() { 
      ivThumb = (ImageView) itemView.findViewById(R.id.ivThumb); 
      tvEmail = (TextView) itemView.findViewById(R.id.tvEmail); 
     } 
    } 
} 
+0

更新像arraylist –

+0

您的數據,但視圖更新內'onBindViewHolder'。即使數據集已更新,「onBindViewHolder」也不會被再次調用。 – user1865027

回答

2

它加載數據滾動時,很多熱門的應用做一個好主意。我個人在這種情況下使用WeakReference。當我開始加載數據時,我在模型中存儲對視圖持有者的弱引用。如果在我得到響應時引用仍然有效,那麼更新視圖是有意義的。如果內存中沒有查看者,那麼它已經被回收了,我不需要更新任何東西。

當調用onViewRecycled時,您可以清除弱引用,也可以考慮取消網絡請求(取決於您的需要)。

緩存與此模型完美配合,您只需在發出網絡請求之前插入此邏輯即可。同樣,這取決於你的需求,也許你根本不需要緩存,或者你的數據很少更新,那麼總是使用緩存直到某個事件纔有意義。

在我的應用程序中,我也使用EventBus,它可以幫助我進行事件處理,但是使用Android SDK和支持庫絕對沒問題。

如果您需要根據用戶是否立即滾動列表來區分項目行爲,還可以添加ScrollListener。例如。在我的應用程序中,如果列表已加載,並且用戶沒有滾動它(改善與用戶的交互),我會對數據進行動畫處理。當用戶滾動時,我會按原樣加載數據,因爲如果我爲數據設置動畫效果,屏幕上的運動就會太多。

+0

聽起來很有希望。我從來沒有使用或聽說過'WeakReference'。現在猜猜它的谷歌時間 – user1865027

+0

'WeakReference'有助於防止內存泄漏。你不希望你的網絡請求阻止GC收集一個未使用的'View',如果你持有一個強大的參考,這將會發生。 –

+1

你有沒有例子?從我剛剛搜索的內容中,簡單地將其從'ImageView'更改爲'WeakReference ',但我仍然看到我的視圖在它真正顯示正確的視圖前被更新了幾次。 (這意味着它仍然顯示位置0到10的數據) – user1865027

相關問題