tccpg288 tccpg288 - 2 months ago 25
Java Question

Resetting/Clearing A RecylerView

I am using a combination of Retrofit/Picasso/Recyclerview to load images into a GridLayoutManager. I have a search bar, and a user types in a term to query FlickR and populate results based on the search term.

The problem is I want to assume that a user may want to re-search a different term. If that is the case, I would want to clear the RecyclerView, re-query FlickR, and then re-populate the images into the RecyclerView. Seems like a lot of activity and I am sure there is an easy way to implement:

public class NewImageActivity extends AppCompatActivity {

private SearchView mSearchView;
private RecyclerView mImageResults;
private RecyclerView.Adapter mImageResultsAdapter;
private ArrayList<Photo> mPhotoArray;
private ArrayList<String> mPhotoURLS;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_image);
if(getSupportActionBar() != null){
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
}

mImageResults = (RecyclerView) findViewById(R.id.flickr_image_results_view);
GridLayoutManager glm = new GridLayoutManager(this, 2);
glm.setOrientation(LinearLayoutManager.VERTICAL);
mImageResults.setLayoutManager(glm);
mImageResults.setItemAnimator(new DefaultItemAnimator());
mImageResultsAdapter = new MyAdapter(mPhotoURLS);
mImageResults.setAdapter(mImageResultsAdapter);
int spanCount = 2; // 3 columns
int spacing = 25; // 50px
boolean includeEdge = false;
mImageResults.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, includeEdge));
mPhotoURLS = new ArrayList<>();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_search, menu);
// Retrieve the SearchView and plug it into SearchManager
MenuItem searchItem = menu.findItem(R.id.search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchItem.expandActionView();
MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
Toast.makeText(getApplicationContext(), "Open", Toast.LENGTH_LONG).show();
return true;
}

@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
Toast.makeText(getApplicationContext(), "Back_Press", Toast.LENGTH_LONG).show();
finish();
return true;
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
View view = getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
//the urls to populate the Recyclerview; URLs dumped into Picasso
mPhotoURLS.clear();
mImageResultsAdapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(), query, Toast.LENGTH_LONG).show();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.flickr.com/services/rest/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();


ApiInterface apiInterface = retrofit.create(ApiInterface.class);
Call<Flicker> call = apiInterface.getImages(query);
call.enqueue(new Callback<Flicker>() {
@Override
public void onResponse(Call<Flicker> call, Response<Flicker> response) {
Log.v("RESPONSE_CALLED", "ON_RESPONSE_CALLED");
String didItWork = String.valueOf(response.isSuccessful());
Log.v("SUCCESS?", didItWork);
Log.v("RESPONSE_CODE", String.valueOf(response.code()));
Flicker testResponse = response.body();
Log.v("RESPONSE_BODY", "response:" + testResponse);
String total = response.body().getPhotos().getTotal().toString();
Log.v("Total", total);
List<Photo> photoResults = response.body().getPhotos().getPhoto();
int numberOfPages = response.body().getPhotos().getPages();
for (int i = 0; i < numberOfPages; i++) {
for (Photo photo : photoResults) {
if (photo.getUrl_m() != null) {
String photoURL = photo.getUrl_m();
Log.v("PHOTO_URL:", photoURL);
mPhotoURLS.add(photoURL);
mImageResultsAdapter.notifyDataSetChanged();
}
}


}

}

@Override
public void onFailure(Call<Flicker> call, Throwable t) {

}
});
return true;
}

@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});

return true;
}


public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {




// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
protected ImageView mResultImage;


public ViewHolder(View v) {
super(v);
mResultImage = (ImageView) v.findViewById(R.id.flickr_individual_image);


}
}

// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<String> mDataSet) {
mPhotoURLS = mDataSet;
}

// Create new views (invoked by the layout manager)
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.grid_item, parent, false);
// set the view's size, margins, paddings and layout parameters
return new ViewHolder(v);
}

// Replace the contents of a view (invoked by the layout manager)

//The OutOfBoundsException is pointing here
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Log.v("ON_BIND", "ON_BINDVIEWHOLDER CALLED");
String urlForPhoto = mPhotoURLS.get(position);
Picasso.with(getApplicationContext())
.load(urlForPhoto)
.placeholder( R.drawable.progress_animation )
.into(holder.mResultImage);

}

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return mPhotoURLS.size();
}
}

public void clearData() {
int size = this.mPhotoURLS.size();
if (size > 0) {
for (int i = 0; i < size; i++) {
this.mPhotoURLS.remove(0);
}

mImageResultsAdapter.notifyItemRangeRemoved(0, size);
}
}

public interface ApiInterface {

@GET("?method=flickr.photos.search&api_key=1c448390199c03a6f2d436c40defd90e&format=json&nojsoncallback=1&extras=url_m")
Call<Flicker> getImages(@Query("text") String query);

}


enter image description here

Answer

When you receive the new response, clear the existing data, update the list with new data and finally call the notifydatasetchanged on adapter.

    mPhotoURLS.clear();
    for (int i = 0; i < numberOfPages; i++) {
        for (Photo photo : photoResults) {
            if (photo.getUrl_m() != null) {
                String photoURL = photo.getUrl_m();
                Log.v("PHOTO_URL:", photoURL);
                mPhotoURLS.add(photoURL);                    
            }
        }
    }
    mImageResultsAdapter.notifyDataSetChanged();