Integrating recyclerview with database - java

#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Collections.swap(queuee, viewHolder.getAdapterPosition(), target.getAdapterPosition());
// and notify the adapter that its dataset has changed
adapterr.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
With the above code i m able to swap the items in the recyclerview ,but now the problem is i also want to make the same respective changes to database.
How to go about?
queuee receives the all the data from the database
queuee is a arraylist which is used to set the recyclerview adapter
Regards
Thanks

Adapter:
public class QueueAdapter extends RecyclerView.Adapter<QueueAdapter.MyViewHolder> {
private Context mContext;
public ArrayList<Music> queue;
MediaPlayer mPlayer = new MediaPlayer();
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title,tt,artist;
public Button play,stop;
public ImageButton option;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.songtitle1);
artist = (TextView)view.findViewById(R.id.artist1);
// play = (Button) view.findViewById(R.id.play);
// stop = (Button) view.findViewById(R.id.stop);
// tt = (TextView) view.findViewById(R.id.song_name);
option = (ImageButton) view.findViewById(R.id.option1);
}
}
public QueueAdapter(Context mContext, ArrayList<Music> queue) {
this.mContext = mContext;
this.queue = queue;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.queue_card, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
Music mu1 = queue.get(position);
holder.title.setText(mu1.getTitle());
holder.artist.setText(mu1.getArtist());
final String link =mu1.getUrl();
final String SongName = mu1.getTitle();
}
#Override
public int getItemCount() {
return queue.size();
}
public void removeItem(int position) {
queue.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, queue.size());
}
}
activity:
recyclerView = (RecyclerView) findViewById(R.id.recyclerqueue);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
adapterr = new QueueAdapter(this,queuee);
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
// adapterr.
recyclerView.setAdapter(adapterr);
initSwipe();

In my opinion, you can do it on OnDestroy method in your Activity. Specifically speaking, firstly, you can get all your data from your adapter, and then delete datas in your database, at last, you can save your data obtained from your adapter again. In this moment, the sequence of your datas is what you want, and this way is easy to code. I'd rather you don't
update your database during onMove, because it's too frequently during your drag, and operates all data is easier than two datas in database.

Related

How to update the recycler without changing the list

My Recyclerview is filled with a list containing links to images. But the images can change (let's say the user can draw something on them), but the link to the image itself does not change. I need to make it so that when the image changes, it is also drawn again in the recycler.
notifyDataSetChanged() does not work in this case, apparently because it reacts to changes in the sheet, and in fact there are no changes in the sheet itself, the links are the same in it. But the images are changed by links.
Maybe somehow you can push the recycler so that it is updated or draws items again?
My Activity:
public class MyDrawing extends Fragment {
private RecyclerView recyclerView;
private RecyclerViewAdapter recyclerViewAdapter;
private View root;
private TextView text;
public MyDrawing() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
root = inflater.inflate(R.layout.fragment_my_drawing, container, false);
recyclerView = root.findViewById(R.id.recyclerViewMyDrawing);
text = root.findViewById(R.id.text);
List<CacheImageModel> cacheImageModels = getCacheImageByState();
recyclerViewAdapter = new RecyclerViewAdapter(cacheImageModels, getContext());
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
recyclerView.setAdapter(recyclerViewAdapter);
recyclerViewAdapter.notifyDataSetChanged();
return root;
}
My Adapter:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private List<CacheImageModel> cacheImageModels;
private Context context;
private String imgUrl;
private int imageKey;
private String category;
private String nameImage;
private ProgressBar progressBarItem;
public RecyclerViewAdapter(List<CacheImageModel> cacheImageModels, Context context) {
this.cacheImageModels = cacheImageModels;
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_view_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
imgUrl = cacheImageModels.get(position).getImageCacheUrl();
nameImage = cacheImageModels.get(position).getName();
category = cacheImageModels.get(position).getCategory();
imageKey = cacheImageModels.get(position).getImageKey();
holder.progressBarItem.setVisibility(View.VISIBLE);
holder.relativeLayout.setLayoutParams(new FrameLayout.LayoutParams(MyApp.getScreenWidth(context) / 2,
MyApp.getScreenWidth(context) / 2));
Glide.with(context)
.load(imgUrl)
.listener(new RequestListener<Drawable>() {
#Override
public boolean onLoadFailed(#Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
#Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
holder.progressBarItem.setVisibility(View.GONE);
return false;
}
})
.into(holder.image);
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int posit = holder.getAdapterPosition();
if (posit < 0 || posit >= cacheImageModels.size()) {
Log.d("POSITION", "Number postition " + posit + " its error");
} else {
String urlImagePosition = cacheImageModels.get(posit).getImageCacheUrl();
String namePosition = cacheImageModels.get(posit).getName();
String categoryPosition = cacheImageModels.get(posit).getCategory();
int imageKeyPosition = cacheImageModels.get(posit).getImageKey();
Uri uri = ContentUris.withAppendedId(MCDataContract.CONTENT_URI, imageKeyPosition);
Intent intent = new Intent(v.getContext(),
ColoringActivity.class);
intent.putExtra("urlImagePosition", urlImagePosition);
intent.putExtra("nameImage", namePosition);
intent.putExtra("keyPosition", imageKeyPosition);
intent.putExtra("categoryPosition", categoryPosition);
intent.setData(uri);
v.getContext().startActivity(intent);
}
}
});
}
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
#Override
public int getItemCount() {
return cacheImageModels.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private ImageView image;
private ProgressBar progressBarItem;
private RelativeLayout relativeLayout;
private CardView cardView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
image = itemView.findViewById(R.id.imageView);
progressBarItem = itemView.findViewById(R.id.progressBarItem);
relativeLayout = itemView.findViewById(R.id.parentItem);
cardView = itemView.findViewById(R.id.cardView);
}
}
}
notifyDataSetChanged() is most likely working as planned. You can set a breakpoint in your view holder binding code to check this.
It is more likely that Glide is pulling the cached versions of the images. You will need a way to get Glide to ignore what's in cache and reload from the URL.
This post addresses the same issue and may be of help to you.

RecyclerView is messed up when scrolling

As you can see in the screenshot, my project contains a RecyclerView (for categories of food) which contains more RecyclerViews (for the ingredients). But iv'e got a problem, my RecyclerView is messing up the order. I debuged the project and the parameters are just fine but the RecyclerView is displaying them wrong. As you can see in the picture, Fruits ingredients are displayed in the Dairy category.
IngredientSectionAdapter.Java
(the main adapter,which contain more RecyclerViews)
class SectionViewHolder extends RecyclerView.ViewHolder {
private TextView sectionBtn;
private RecyclerView itemRecyclerView;
public SectionViewHolder(View itemView) {
super(itemView);
sectionBtn = (TextView) itemView.findViewById(R.id.text_category);
itemRecyclerView = (RecyclerView) itemView.findViewById(R.id.ingredientsRecycler);
}
}
private Context context;
private ArrayList<IngredientSectionModel> sectionModelArrayList;
ArrayList<IngredientItemAdapter> adapters;
public IngredientSectionAdapter(Context context, ArrayList<IngredientSectionModel> sectionModelArrayList) {
this.context = context;
this.sectionModelArrayList = sectionModelArrayList;
adapters = new ArrayList<IngredientItemAdapter>();
}
#Override
public SectionViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.parent_list,null);
return new SectionViewHolder(v);
}
#Override
public void onBindViewHolder(SectionViewHolder holder, int position) {
final IngredientSectionModel sectionModel = sectionModelArrayList.get(position);
holder.itemRecyclerView.setTag(holder.itemRecyclerView.getVisibility());
final RecyclerView sectionList = holder.itemRecyclerView;
holder.sectionBtn.setText(sectionModel.getSectionLabel());
//recycler view for items
holder.itemRecyclerView.setHasFixedSize(true);
holder.itemRecyclerView.setNestedScrollingEnabled(false);
/* set layout manager on basis of recyclerview enum type */
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3,1);
adapters.add(new IngredientItemAdapter(context, sectionModel.getItemArrayList()));
int resId = R.anim.grid_layout_animation_from_bottom;
//LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(context, resId);
holder.itemRecyclerView.setLayoutManager(staggeredGridLayoutManager);
holder.itemRecyclerView.setAdapter(adapters.get(position));
//holder.itemRecyclerView.setLayoutAnimation(animation);
//toggle visibilty of inner RecyclerView (ingredients, not categories)
holder.sectionBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (sectionList.getVisibility() == View.VISIBLE){
sectionList.setVisibility(View.GONE);
}
else
{
sectionList.setVisibility(View.VISIBLE);
}
}
});
}
What can cause this?
Every time onBindViewHolder is called you create a new IngredientItemAdapter and add it to your adapters, and then you call holder.itemRecyclerView.setAdapter(adapters.get(position)). However, adapters.get(position) is not the adapter you just created. Your adapter will get bigger and bigger. Try this
IngredientItemAdapter adapter = adapters.get(position);
adapter.setIngredients(sectionModel.getItemArrayList());
holder.itemRecyclerView.setAdapter(adapter);

Data not shown in RecyclerView

I am trying to make a list of items with a Recycler View in a simple way by making a method called Data() that's has a for loop to set the text view continuously but when I run the app it show's me a white screen without anything.
public class MainActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
RecyclerAdapter mAdapter ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView =(RecyclerView) findViewById(R.id.recycler_view);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setAdapter(mAdapter);
}
private class RecyclerAdapter extends RecyclerView.Adapter<MyViewHolder{
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.list_item,parent,false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.Data();
}
#Override
public int getItemCount() {
return 100;
}
}
private class MyViewHolder extends RecyclerView.ViewHolder{
public TextView mmTextView ;
private Button mButton;
public MyViewHolder(View itemView) {
super(itemView);
mmTextView = (TextView) findViewById(R.id.list_text_view);
mButton = (Button) findViewById(R.id.list_button);
}
private void Data (){
for (int i =0 ;i<=100;i++){
mmTextView.setText(String.valueOf("Text : " + i));
}
}
}
}
You should infilate mmTextView from itemView not from Activity. It should be mmTextView = (TextView) itemView.findViewById(R.id.list_text_view);, also since it's a view of holder you can get it in onBindViewHolder() method using holder.mmTextView.setText(). Infilate button on onCreate() of Activity, also it's convenient to pass data to an adapter inside it's constructor and bind data to adapter on onBindViewHolder() method since it knows which views it possesses.
In onBindViewHolder method bind the data into the textView:
mmTextView.mmTextView.setText("SOME STRING VALUE");

Handle recyclerview click in a fragment instead of holder class

I have a fragment that displays a RecyclerView. I am currently handling the onclick event in my holder class like this:
public class CategoryHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public ImageView categoryImageView;
public TextView categoryNameTextView;
public TextView categoryAmountTextView;
ArrayList<Category> categoriesArrayList = new ArrayList<>();
Context context;
public CategoryHolder(View itemView, Context context, ArrayList<Category> categories) {
super(itemView);
this.categoriesArrayList = categories;
this.context = context;
itemView.setOnClickListener(this);
this.categoryImageView = (ImageView) itemView.findViewById(R.id.categoryImageView);
this.categoryNameTextView = (TextView) itemView.findViewById(R.id.categoryNameTextView);
this.categoryAmountTextView = (TextView) itemView.findViewById(R.id.categoryAmountTextView);
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
Category category = this.categoriesArrayList.get(position);
Toast.makeText(context, ""+category.getCategoryName() + position,
}
}
As you can see I have implemented OnClickListener in the holder class and then setTheOnItemClickListner in the Holder.
In my Adapter I pass the holder class the the arraylist with the data like this:
Context context;
ArrayList<Category> categories;
public CategoriesAdapter(Context context, ArrayList<Category> categories) {
this.context = context;
this.categories = categories;
}
#Override
public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.categorylist_singlecell, parent, false);
CategoryHolder holder = new CategoryHolder(v, context, categories);
return holder;
}
I am passing the data when creating the new holder.
This works fine and I can toast the position and any of the data from the ArrayList that is used for the RecyclerView.
What I want to do though is use that in the main fragment where I initialise the RecyclerView and adapter.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_nested_youtube_video_selection, container, false);
//////////////////////////// CATEGORIES RECYCLER /////////////////////////////////////
// Initialise the categories Recylerview
LinearLayoutManager categoriesLayoutManger = new LinearLayoutManager(getActivity());
categoriesLayoutManger.setOrientation(LinearLayoutManager.HORIZONTAL);
categoriesRecyclerView = (RecyclerView) view.findViewById(R.id.youtubeAlarmCategoryRecyclerView);
categoriesRecyclerView.setLayoutManager(categoriesLayoutManger);
// Get the data for the categories RecyclerView
categoryArraylist = CategoryCollection.getCategoryArrayList();
// Initialse the categories RecyclerView Adapter
categoriesAdapter = new CategoriesAdapter(getActivity(), categoryArraylist);
// Bind the categories Adapter to the categories RecyclerView
categoriesRecyclerView.setAdapter(categoriesAdapter);
I am thinking I need an interface but I am not sure how to do that or if that is even the best way to do it.
Following should work:
create an interface
create an instance of this interface in your fragment and pass it on to the adapter
let the adapter pass this interface on to the view holder
let the view holder define an onClickListener that passes the event on to the interface
Here's an example:
Interface
public interface ItemClickListener {
void onItemClicked(ViewHolder vh, Object item, int pos);
}
public interface GenericItemClickListener<T, VH extends ViewHolder> {
void onItemClicked(VH vh, T item, int pos);
}
ViewHolder
public class CategoryHolder extends RecyclerView.ViewHolder {
public CategoryHolder(View itemView, Context context) {
super(itemView);
this.context = context;
this.categoryImageView = (ImageView) itemView.findViewById(R.id.categoryImageView);
this.categoryNameTextView = (TextView) itemView.findViewById(R.id.categoryNameTextView);
this.categoryAmountTextView = (TextView) itemView.findViewById(R.id.categoryAmountTextView);
}
}
Adapter
Context context;
ArrayList<Category> categories;
ItemClickListener itemClickListener;
public CategoriesAdapter(Context context, ArrayList<Category> categories, ItemClickListener itemClickListener) {
this.context = context;
this.categories = categories;
this.itemClickListener = itemClickListener;
}
// DON'T PASS YOUR DATA HERE, just create a ViewHolder
#Override
public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.categorylist_singlecell, parent, false);
CategoryHolder holder = new CategoryHolder(v, context);
return holder;
}
//HERE you bind one item of your list to the view holder
#Override
public void onBindViewHolder(final CategoryHolder vh, final int i) {
final Category category = categories.get(i);
// set click listener
vh.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
itemClickListener.onItemClicked(vh, category, i);
}
});
// update images and texts...
}
Edit
Updated the code to show you, that you should not pass a array of items to every view holder... The view holder gets created and reused, only update the view holder in onBindViewHolder and bind the view holder instance to the correct data there...
Btw, I would make a generic interface instead, that's even more beautiful... My example is just a simple solution...
Edt 2 - How to create the interface instance
ItemClickListener listener = new ItemClickListener(){
#Override
public void onItemClicked(RecyclerView.ViewHolder vh, Object item, int pos){
Toast.makeText(getActivity(), "Item clicked: " + pos, Toast.LENGTH_SHORT).show();
}
};
abstract YOURAdapter class then add method like
void onLikeClicked(Object object, int position);
void onItemClicked();
call it in bindView as simply like
holder.btnLike.setOnclickListner(new OnClickListner){
onLikeClicked(list.get(position), position);
}
In Activity Class
now it will automatically implements all methods of adapter
YOURAdapter adapter=new YOURAdapter(){
void onLikeClicked(Object object, int position){
}
void onItemClicked(){
}
}

HorizontalGridView/ RecyclerView scroll position resets once Picasso image loads

I have a HorizontalGridView and all is working well, however I am loading images with Picasso and whenever an image loads, the HorizontalGridView snaps back to the first item/starting scroll position. I also have a map fragment on the activity and notice that when the map is interacted with, the HorizontalGridView displays the the same behavior. Below is the adapter code. Please help, have been stuck on this one for a couple of days now...
public class GridElementAdapter extends RecyclerView.Adapter<GridElementAdapter.SimpleViewHolder>{
private Context context;
private Deal[] mDeals;
public GridElementAdapter(Context context, Deal[] deals){
this.context = context;
this.mDeals = deals;
}
public static class SimpleViewHolder extends RecyclerView.ViewHolder {
public final ImageView dealImage;
public final TextView dealTitle;
public final TextView dealSubtitle;
public final TextView dealPrice;
public final TextView dealTime;
public final TextView dealDays;
public SimpleViewHolder(View view) {
super(view);
dealImage = (ImageView) view.findViewById(R.id.gridDealImageView);
dealTitle = (TextView) view.findViewById(R.id.gridTitleLabel);
dealSubtitle = (TextView) view.findViewById(R.id.gridSubtitleLabel);
dealPrice = (TextView) view.findViewById(R.id.gridPriceLabel);
dealTime = (TextView) view.findViewById(R.id.gridAvailableTimeLabel);
dealDays = (TextView) view.findViewById(R.id.gridAvailableDaysLabel);
}
}
#Override
public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(this.context).inflate(R.layout.deal_grid_item, parent, false);
return new SimpleViewHolder(view);
}
#Override
public void onBindViewHolder(SimpleViewHolder holder, final int position) {
String dealImageUrl = "http://api.cheapeat.com.au/deals/" + mDeals[position].getPhotoId() + "/photo";
Context context = holder.dealImage.getContext();
Picasso.with(context).load(dealImageUrl).placeholder(R.drawable.deal_image_placeholder).into(holder.dealImage);
holder.dealTitle.setText(mDeals[position].getName());
holder.dealPrice.setText(mDeals[position].getPriceData());
holder.dealSubtitle.setText(mDeals[position].getDescription());
holder.dealTime.setText(mDeals[position].getAvailabilityTime());
holder.dealDays.setText(mDeals[position].getFormattedAvailableDays(mDeals[position].getAvailabilityDay()));
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemCount() {
return this.mDeals.length;
}
}
So I finally managed to solve this one. Turns out I hadn't set the LayoutManager for the HorizontalGridView. Specifically, in the activity where I set the adapter:
// Had this
horizontalGridView = (HorizontalGridView) findViewById(R.id.gridView);
GridElementAdapter adapter = newGridElementAdapter(VenueProfileActivity.this, mDeals);
horizontalGridView.setAdapter(adapter);
// This needed to be added
HorizontalGridView.LayoutManager layoutManager = new LinearLayoutManager(VenueProfileActivity.this, LinearLayoutManager.HORIZONTAL, false);
horizontalGridView.setLayoutManager(layoutManager);
horizontalGridView.setHasFixedSize(true);
Hopefully this saves some headaches, as I've seen this question floating around with no correct solution yet.

Categories

Resources