2017-02-25 74 views
0

我試圖在有人搜索某個單詞時替換我的RecyclerView中的項目。 GIF列表被髮送到我的回調方法中,並且我遍歷了這些對象,並且想要替換RecyclerView中的每個對象。但是,當我嘗試執行此操作時,如果我在我的適配器中調用ArrayList.set(),則會發生IndexOutOfBoundsException。更換RecyclerView項目時獲取IndexOutOfBoundsException

我得到它發生的原因......我的適配器中的ArrayList中有零個項目。我的問題是爲什麼?我究竟做錯了什麼?

我的活動代碼:

package hidden.package; 

// Imports hidden 

public class GifSearchActivity extends AppCompatActivity { 

    @BindView(R.id.gifSearchBar) 
    FloatingSearchView searchGifs; 

    @BindView(R.id.gifSearchResults) 
    RecyclerView searchResults; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_gifsearch); 
     ButterKnife.bind(this); 

     final GIFResultsAdapter adapter = new GIFResultsAdapter(); 

     final SharedPreferences prefs = PreferenceManager 
       .getDefaultSharedPreferences(GifSearchActivity.this); 

     final GIFInterface i = new GIFInterface(); 
     i.setSearchListener(new GIFInterface.GIFSearchListener() { 
      @Override 
      public void onSearchResultsRetrieved(final GIFSearchResults gifSearchResults) { 
       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         Log.d("GAB", "Results Retrieved..."); 
         int count = 0; 
         for (GIF gif : gifSearchResults.getGIFs()) { 
          adapter.replaceItem(gif, count); 
          count++; 
         } 
        } 
       }); 
      } 
     }); 

     searchResults.setLayoutManager(new GridLayoutManager(getBaseContext(), 1, GridLayoutManager.VERTICAL, false)); 
     searchResults.setItemAnimator(new DefaultItemAnimator()); 
     searchResults.setAdapter(adapter); 

     searchGifs.setOnQueryChangeListener(new FloatingSearchView.OnQueryChangeListener() { 
      @Override 
      public void onSearchTextChanged(String oldQuery, String newQuery) { 
       i.searchForGif(prefs.getString("token", ""), newQuery); 
      } 
     }); 
    } 
} 

我的適配器代碼:

package hidden.package; 

// Imports hidden 

@SuppressWarnings("deprecation") 
public class GifResultsAdapter extends RecyclerView.Adapter<GifResultsAdapter.GifsViewHolder> { 

    private ArrayList<GIF> gifs = new ArrayList<>(); 
    private Context con; 

    public class GifsViewHolder extends RecyclerView.ViewHolder { 

     ImageView gif; 
     ProgressBar gifProgressBar; 

     public GifsViewHolder(View itemView) { 
      super(itemView); 
      gif = (ImageView) itemView.findViewById(R.id.gif); 
      gifProgressBar = (ProgressBar) itemView.findViewById(R.id.gifProgressBar); 
     } 
    } 

    public void replaceItem(GIF gif, int position) { 
     gifs.set(position, gif); 
     notifyItemChanged(position); 
    } 

    @Override 
    public GifsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     Log.d("GAB", "ViewHolder Created"); 
     View itemView = LayoutInflater.from(parent.getContext()) 
       .inflate(R.layout.util_gif_row, parent, false); 
     this.con = parent.getContext(); 
     return new GifsViewHolder(itemView); 
    } 

    @Override 
    public void onBindViewHolder(final GifsViewHolder holder, int position) { 
     Log.d("GAB", "ViewHolder bound"); 
     final GIF gif = gifs.get(position); 
     Glide.with(con) 
       .load(gif.getUrl()) 
       .override(700, 700) 
       .fitCenter() 
       .placeholder(new ColorDrawable(AndroidHelper.darkenColor(con.getResources().getColor(R.color.colorAccent), 0.95f))) 
       .into(holder.gif); 
    } 

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

編輯:這裏是例外...

02-25 00:41:46.371 29205-29205/ai.gab.android E/UncaughtException: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 
    at java.util.ArrayList.set(ArrayList.java:427) 
    at ai.gab.android.ui.adapter.GIFResultsAdapter.replaceItem(GIFResultsAdapter.java:59) 
    at ai.gab.android.ui.activity.GifSearchActivity$1$1.run(GifSearchActivity.java:68) 
    at android.os.Handler.handleCallback(Handler.java:751) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:154) 
    at android.app.ActivityThread.main(ActivityThread.java:6119) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 

一套全新的眼光,將不勝感激!

+0

我應該提到,起初,我嘗試將GIF添加到RV ...但是最終添加了用戶所做的每個查詢的GIF。因此,如果我輸入'angry',它將以gif的形式加載查詢'a','an','ang'等,這就是爲什麼我要替換結果的原因。 –

+0

您創建一個GIF對象的空列表('gifs')。你需要在構造函數中傳遞你的列表(例如) – GVillani82

回答

0

我想出了一個更好的解決方案:創建一個clear()方法,並調用,當搜索查詢的變化。

特別感謝this SO answer。現在,每當搜索查詢發生變化時,當前項目將被刪除,並且新項目將被添加進來。

0

您所呼叫的方法是replaceItem它取代的元素與另外一個,你的情況,你調用它,當你的列表是空的,你應該先的方法創建添加照片與圖像在適配器

public void addItem(GIF gif) { 
    gifs.add(gif); 
    notifyItemChanged(position); 
} 

,而不是調用replaceItem你第一次得到一個GIF,你應該叫後addItem

當你需要更換一個特定的元素,你可以使用replaceItem

0

我會做些稍微不同的事情。我會在每個按鍵上等待一段時間,大約50/100ms,並且需要新的內容加載(可能使用加載器)。

通過這種方式,您可以防止觸發大量可能的大量無用的搜索,並在此之後替換適配器的所有內容,以使用新的結果集合。

在下面我將使用的AsyncTask只是要快

在你GifSearchActivity添加一個名爲gifSearchTask變量下面定義的的AsyncTask以及與此替換YOUT查詢更改偵聽器的例子。

通過這種方式,您將針對每個查詢更改觸發一個事件,取消之前的if正在運行或掛起。用新的查詢開始新的查詢,最後用新的查詢替換回收查看的整個數據集。

searchGifs.setOnQueryChangeListener(new FloatingSearchView.OnQueryChangeListener() { 
     @Override 
     public void onSearchTextChanged(String oldQuery, String newQuery) { 
      if (gifSearchTask != null && AsyncTask.Status.FINISHED != gifSearchTask.getStatus()) { 
       gifSearchTask.cancel(true); 
      } 
      gifSearchTask = new GifSearchAsyncTask(); 
      gifSearchTask.execute(newQuery); 
     } 
    }); 


class GifSearchAsyncTask extends AsyncTask<String, Void, List<Gif>> { 

    @Override 
    protected List<Gif> doInBackground(String... params) { 
     List<Gif> results = null; 
     android.os.SystemClock.sleep(100); 
     // if not cancelled 
     if (!isCancelled()) { 
      results = performSearch(params); 
     } 
     return results; 
    } 

    @Override 
    protected void onCancelled() { 
     // do nothing 
    } 

    @Override 
    protected void onCancelled(Result result) { 
     // do nothing 
    } 

    @Override 
    protected void onPostExecute(List<Gif> results) { 
     adapter.setData(results); 
     gifSearchTask = null; 
    } 

    private List<Gif> performSearch(String ... params) { 
     // perform search and retur the results 
    } 
}