Items in RecyclerView do remain as it is in android - android

In below image, when user clicks on the item of recyclerview, "ADDED TO WORDS"
ADDED TO WORDS
But after closing and opening the App again, it changes back to "ADD TO WORDS"
ADD TO WORDS
I want to keep this same when user reopens the app.
TodayFragment.java
public class TodayFragment extends Fragment {
private RecyclerView wordRecyclerView;
private DbHelper dbHelper;
private SQLiteDatabase mDatabase;
private Context mContext;
WordAdapter mWordAdapter;
private static final String LOG_TAG = "TodayFragment";
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dbHelper = new DbHelper(mContext);
mDatabase = dbHelper.getWritableDatabase();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d(LOG_TAG,"onAttach");
mContext = context;
}
#Override
public void onDetach() {
super.onDetach();
Log.d(LOG_TAG,"onDetach");
mContext = null;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_today,container,false);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
wordRecyclerView = view.findViewById(R.id.word_recycler_view);
// wordRecyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setReverseLayout(true);
linearLayoutManager.setStackFromEnd(true);
wordRecyclerView.setLayoutManager(linearLayoutManager);
String query = "select * from wordhistory;";
Cursor c = mDatabase.rawQuery(query, new String[] {});
Log.d(LOG_TAG,"cursor count, "+c.getCount());
Log.d(LOG_TAG,"onViewCreated set recycler view");
mWordAdapter = new WordAdapter(mContext);
wordRecyclerView.setAdapter(mWordAdapter);
mWordAdapter.swapCursor(c);
mWordAdapter.notifyDataSetChanged();
}
}
fragment_today.xml
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
tools:context=".fragment.TodayFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:id="#+id/word_recycler_view" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
WordAdapter.java
public class WordAdapter extends BaseCursorAdapter<WordAdapter.WordViewHolder> {
private static final String LOG_TAG = "WordAdapter";
Context mContext;
private OnItemClickListener mListener;
private int touchCount=0;
Cursor mCursor;
public WordAdapter(Context mContext) {
super(null);
this.mContext = mContext;
}
public interface OnItemClickListener{
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener){
mListener = listener;
}
#NonNull
#Override
public WordViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view;
view = layoutInflater.inflate(R.layout.word_card_layout,parent,false);
Log.d(LOG_TAG,"onCreateViewHolder: ");
return new WordViewHolder(view);
}
#Override
public void onBindViewHolder(WordViewHolder holder, Cursor cursor) {
int wordColumnIndex = cursor.getColumnIndex(DictionaryContract.DictionaryEntry.COLUMN_WORD);
int defColumnIndex = cursor.getColumnIndex(DictionaryContract.DictionaryEntry.COLUMN_WORD_DEFINITION);
int audioColumnIndex = cursor.getColumnIndex(DictionaryContract.DictionaryEntry.COLUMN_WORD_AUDIOURL);
int synonymColumnIndex = cursor.getColumnIndex(DictionaryContract.DictionaryEntry.COLUMN_WORD_SYNONYMS);
int antonymColumnIndex = cursor.getColumnIndex(DictionaryContract.DictionaryEntry.COLUMN_WORD_ANTONYMS);
String wordStr = cursor.getString(wordColumnIndex);
String wordDefStr = cursor.getString(defColumnIndex);
String audioStr = cursor.getString(audioColumnIndex);
String synonymStr = cursor.getString(synonymColumnIndex);
String antonymStr = cursor.getString(antonymColumnIndex);
Log.d(LOG_TAG,"onBindViewHolder wordStr: "+wordStr);
Log.d(LOG_TAG,"onBindViewHolder wordDefStr: "+wordDefStr);
holder.wordTextView.setText(wordStr);
holder.defTextView.setText(wordDefStr);
}
/* #Override
public int getItemCount() {
return mCursor.getCount();
}*/
#Override
public void swapCursor(Cursor newCursor) {
super.swapCursor(newCursor);
}
public class WordViewHolder extends RecyclerView.ViewHolder {
TextView wordTextView;
ImageView audioImageView;
TextView defTextView;
TextView wordTrickTextView;
TextView defTrickTextView;
ImageView shareImageView;
ImageView favUnselectImageView;
ImageView favSelectImageView;
TextView addWordTextView;
TextView addedWordTextView;
ImageView tickImageView;
RelativeLayout addWordRelativeLayout;
public WordViewHolder(#NonNull View itemView) {
super(itemView);
Log.d(LOG_TAG,"WordViewHolder itemView: "+itemView);
wordTextView = itemView.findViewById(R.id.wordText);
audioImageView = itemView.findViewById(R.id.wordAudio);
defTextView = itemView.findViewById(R.id.wordDef);
wordTrickTextView = itemView.findViewById(R.id.memorisingTrickWord);
defTrickTextView = itemView.findViewById(R.id.memorisingTrickDef);
shareImageView = itemView.findViewById(R.id.wordShare);
favUnselectImageView = itemView.findViewById(R.id.wordFavUnselect);
favSelectImageView = itemView.findViewById(R.id.wordFavSelect);
addWordTextView = itemView.findViewById(R.id.addWordText);
addedWordTextView = itemView.findViewById(R.id.addedWordText);
tickImageView = itemView.findViewById(R.id.tickImage);
addWordRelativeLayout = itemView.findViewById(R.id.addWordRelativeLayout);
addedWordTextView.setVisibility(View.GONE);
tickImageView.setVisibility(View.GONE);
addWordRelativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (touchCount==0){
addWordTextView.setVisibility(View.GONE);
addedWordTextView.setVisibility(View.VISIBLE);
tickImageView.setVisibility(View.VISIBLE);
((Animatable) tickImageView.getDrawable()).start();
touchCount=1;
} else{
addWordTextView.setVisibility(View.VISIBLE);
addedWordTextView.setVisibility(View.GONE);
tickImageView.setVisibility(View.GONE);
((Animatable) tickImageView.getDrawable()).stop();
touchCount=0;
}
}
});
}
}
}
User should be able to see those changes they did in any item of recycler view even after reopening the app

When you close an app, the system automatically destroys the activity. Thus when you open it again, the activity is recreated.
You can save data for the activity before the activity is destroyed using savedInstanceState.
You need to override the onSaveInstanceState method in your activity and add to the bundle. Below is an example code:
#Override
public void onSaveInstanceState(Bundle saveInstanceState){
// example, save if text is added
saveInstanceState.putBoolean("Herbivore", true);
super.onSaveInstanceState(saveInstanceState);
}
Then when your activity starts, you can receive the bundle from OnCreate.
#Override
boolean herbivoreAdded;
public void OnCreate(Bundle onSaveInstanceState){
super.OnCreate(saveInstanceState);
// access saved value
herbivoreAdded = saveInstanceState.getBoolean("Herbivore");
}

Related

Recycler view only updates when I reopen the Activity after deleting from Room Database

I have this fragment with a Recycler view that shows content from a Room Database. In my adapter I have a ImageButton that when is clicked removes the item from the list. I can confirm that the item is removed from the database but my list is not having the expected behavior. In order to it to be updated I have to open the activity again.
Recycler View
public class WishlistFragment extends Fragment {
private static WishlistAdapter mAdapter;
private RecyclerView mRecyclerView;
protected static List<String> wishlist;
private Context context;
protected static OnRestaurantClickedListener listener;
private FirebaseAuth mAuth;
public static WishlistAdapter getmAdapter() {
return mAdapter;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = getContext();
mAuth = FirebaseAuth.getInstance();
wishlist = new ArrayList<>();
mAdapter = new WishlistAdapter(context, wishlist,getActivity(),mAuth.getCurrentUser().getUid());
LoadWishlistTask lwt=new LoadWishlistTask(getActivity(),wishlist,mAdapter,mAuth.getCurrentUser().getUid());
lwt.execute();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mContentView = inflater.inflate(R.layout.restaurants_list, container, false);
mRecyclerView = mContentView.findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContentView.getContext()));
mRecyclerView.setAdapter(mAdapter);
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(itemDecoration);
return mContentView;
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
listener = (OnRestaurantClickedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnRestaurantClickedClicked");
}
}
}
Adapter
public class WishlistAdapter extends RecyclerView.Adapter<WishlistAdapter.WishlistViewHolder> {
private Context mContext;
private List<String> mRestaurantIds;
private Activity act;
private String currentUserId;
public WishlistAdapter(Context context, List<String> ids,Activity activity,String currentUser) {
mRestaurantIds=ids;
mContext = context;
act=activity;
currentUserId=currentUser;
}
#Override
public WishlistViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// Get layout inflater from context
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate layout
View rView = inflater.inflate(R.layout.item_restaurant, parent, false);
// Return a new holder instance
return new WishlistViewHolder(rView);
}
#Override
public void onBindViewHolder(final WishlistViewHolder viewHolder, final int position) {
// Get the data model based on position
final String id = mRestaurantIds.get(position);
getApi().getRestaurantDetails(Integer.parseInt(id), "75be9f9e2239fe637bf9cb1b46979d91")
.enqueue(new Callback<Restaurant_>() {
#Override
public void onResponse(Call<Restaurant_> call, Response<Restaurant_> response) {
final TextView name=viewHolder.nameTextView;
name.setText(response.body().getName());
final TextView rating=viewHolder.ratingTextView;
rating.setText(response.body().getUserRating().getAggregateRating());
final ImageButton remove=viewHolder.removeButton;
remove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Wishlist deletedRestaurant=new Wishlist(currentUserId,id);
RemoveWLTask rt=new RemoveWLTask(deletedRestaurant,act,WishlistFragment.wishlist);
rt.execute();
}
});
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
WishlistFragment.listener.onRestaurantClicked(id);
}
});
}
#Override
public void onFailure(Call<Restaurant_> call, Throwable t) {
AlertDialog.Builder builder = new AlertDialog.Builder(act);
builder.setMessage("CouldnĀ“t load restaurant details");
AlertDialog mDialog = builder.create();
mDialog.show();
}
});
}
#Override
public int getItemCount() {
return mRestaurantIds.size();
}
private Retrofit getRetrofit() {
return new Retrofit.Builder()
.baseUrl("https://developers.zomato.com/api/v2.1/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
private ZomatoApi getApi() {
return getRetrofit().create(ZomatoApi.class);
}
public class WishlistViewHolder extends RecyclerView.ViewHolder {
public TextView nameTextView;
public TextView ratingTextView;
public TextView distanceTextView;
public ImageButton removeButton;
public WishlistViewHolder(View itemView) {
super(itemView);
nameTextView = itemView.findViewById(R.id.restaurantName);
ratingTextView=itemView.findViewById(R.id.restaurantRating);
distanceTextView=itemView.findViewById(R.id.restaurantDistance);
removeButton=itemView.findViewById(R.id.wishlistButton);
}
}
}
Remove Task
public class RemoveWLTask extends AsyncTask<Void,Void,Void> {
private Wishlist deletedRestaurant;
private DB db;
private Activity activity;
private List<String> wishlist;
public RemoveWLTask (Wishlist deletedRestaurant, Activity activity,List<String> wishlist) {
this.deletedRestaurant=deletedRestaurant;
this.activity=activity;
this.db= Room.databaseBuilder(activity.getApplicationContext(), DB.class, "sample-db").build();
this.wishlist=wishlist;
}
#Override
protected Void doInBackground(Void... voids) {
while (!isCancelled()){
db.daoAcess().deleteFromWishlist(deletedRestaurant);
break;
}
return null;
}
#Override
protected void onPostExecute (Void aVoid) {
int index = wishlist.indexOf(deletedRestaurant);
wishlist.remove(deletedRestaurant);
WishlistFragment.getmAdapter().notifyItemRemoved(index);
WishlistFragment.getmAdapter().notifyItemRangeChanged(index, wishlist.size());
}
}
Found the error, I need to pass deletedRestaurant.getRestaurantId() as argument instead of deletedRestaurant

Need explanation on sending data from adapter to fragment

I want to send data from an adapter to a fragment that is already open.
In the main activity, there are two fragments already open, fragment A and fragment B. In fragment A, I have a RecyclerView and CardView placed. When one of the card views is clicked, I want to send its data to fragment B. And I get an NPE when calling mCallbacks.
if (mCallbacks != null){
mCallbacks.onItemClicked(strStockName);}
In this case, I used an interface. But I need more explanation about it.
Here is my adapter's code:
public class adapterStock extends RecyclerView.Adapter<adapterStock.ViewHolder> {
private String[] stockNameDataSet;
private Context mContext;
//==============================================
//---- interface
public interface Callbacks{
public void onItemClicked(String StockName);
}
private Callbacks mCallbacks;
//==============================================
public adapterStock(Context context, String[] DataSet){
stockNameDataSet = DataSet;
mContext = context;
}
#NonNull
#Override
public adapterStock.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext());
View view = layoutInflater.inflate(R.layout.cv_stock, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
final String strStockName = stockNameDataSet[position];
holder.tbxStockName.setText(stockNameDataSet[position]);
holder.cardView.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
Snackbar.make(view, "Stock "+strStockName, Snackbar.LENGTH_LONG).show();
if (mCallbacks != null){
mCallbacks.onItemClicked(strStockName);
}
}
});
}
#Override
public int getItemCount() {
return stockNameDataSet.length;
}
public static class ViewHolder extends RecyclerView.ViewHolder{
public View view;
public TextView tbxStockName;
public CardView cardView;
public ViewHolder(View v){
super (v);
tbxStockName = (TextView) v.findViewById(R.id.cvTbxItemStockName);
cardView = (CardView) v.findViewById(R.id.cvStock);
}
}
public void setCallbacks(Callbacks callbacks){
this.mCallbacks = callbacks;
}
}
And here is fragment A:
public class AFrag extends Fragment implements adapterStock.Callbacks {
private String strStockName;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.frag_A, container, false);
tbxStock = (TextView) view.findViewById(R.id.tbxR);
return view;
}
#Override
public void onItemClicked(String StockName) {
Toast.makeText(getActivity(), "Stock terpilih " + StockName, Toast.LENGTH_LONG).show();
tbxStock.setText(strStockName);
}
}
Suggestions are appreciated. Thanks.
Include, setCallbacks(this) in your fragment A once adapterStock instance is created.
setCallbacks(this) in your fragment
Change this
public adapterStock(Context context, String[] DataSet){
stockNameDataSet = DataSet;
mContext = context;
}
to this
public adapterStock(Context context, String[] DataSet, Callbacks mCallbacks){
stockNameDataSet = DataSet;
mContext = context;
this.mCallbacks=mCallbacks;
}
in fragment's adapterStock instance, pass the mCallbacks as this (i.e., new adapterStock(context, dataset,this))
note: two other answers also correct

How can I call and display a Fragment inside a Fragment when an item from the RecycleView is clicked?

I am using Fragments (fragment_inventory.xml) and inside that are 2 Fragments as you can see the picture below. The left part is the Fragment with a RecycleView.
What I want to do is that when I click an option from the RecycleView from the options, let's say Categories is that a CategoryFragment will display on the right side of the Fragment.
I have this following code working from the past with ListView (Please see snippet below). But when I add it to my InventoryRecyclerViewAdapter.java (from the I want to insert code here spacing) is the getFragmentManager() will turn red.
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
switch (position){
case 0:
ProductsFragment productsFragment = new ProductsFragment();
fragmentTransaction.replace(R.id.inventorylist_fragmentcontainer, productsFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
break;
Can you please advise me on what to do with this? Also, I want the selected RecycleView to be highlighted when clicked. Thanks
InventoryRecyclerViewAdapter.java
public class InventoryRecyclerViewAdapter extends RecyclerView.Adapter<InventoryRecyclerViewAdapter.ViewHolder>{
private static final String TAG = "RecyclerViewAdapter";
private ArrayList<Integer> mIcon = new ArrayList<>();
private ArrayList<String> mLabel = new ArrayList<>();
private Context context;
public InventoryRecyclerViewAdapter(Context context, ArrayList<Integer> mIcon, ArrayList<String> mLabel) {
this.mIcon = mIcon;
this.mLabel = mLabel;
this.context = context;
}
//responsible for inflating the view
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.customlayout_inventorylist, viewGroup, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull InventoryRecyclerViewAdapter.ViewHolder viewHolder, final int i) {
Log.d(TAG, "onBindViewHolder: called.");
Glide.with(context)
.asBitmap()
.load(mIcon.get(i))
.into(viewHolder.icon);
viewHolder.label.setText(mLabel.get(i));
viewHolder.customLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
----------------------------------------
I want to insert a code here
----------------------------------------
});
}
#Override
public int getItemCount() {
return mLabel.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
ImageView icon;
TextView label;
LinearLayout customLayout;
public ViewHolder(#NonNull View itemView) {
super(itemView);
icon = itemView.findViewById(R.id.inventorylist_icon);
label = itemView.findViewById(R.id.inventorylist_title);
customLayout = itemView.findViewById(R.id.inventoryoptions_layout);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
}
}
public interface onInventoryListener{
void onInventoryClick(int position);
}
InventoryListFragment.java
public class InventoryListFragment extends Fragment implements InventoryRecyclerViewAdapter.onInventoryListener{
private static final String TAG = "InventoryListFragment";
//variables
private ArrayList<Integer> mIcon = new ArrayList<>();
private ArrayList<String> mLabel = new ArrayList<>();
public InventoryListFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_inventory_list, container, false);
Log.d(TAG, "onCreateView: started");
initImageBitmaps(view);
return view;
}
private void initImageBitmaps(View view){
Log.d(TAG, "initImageBitmaps: preparing bitmaps");
mIcon.add(R.drawable.ic_product);
mLabel.add("Products");
mIcon.add(R.drawable.ic_customer);
mLabel.add("Services");
mIcon.add(R.drawable.ic_category);
mLabel.add("Categories");
mIcon.add(R.drawable.ic_tag);
mLabel.add("Discounts");
initRecyclerView(view);
}
private void initRecyclerView(View view){
RecyclerView recyclerView = view.findViewById(R.id.inventorylist_recycleview);
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity())
.build()); //adding a divider into the recyclerview list
InventoryRecyclerViewAdapter adapter = new InventoryRecyclerViewAdapter(getActivity(), mIcon, mLabel);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
//method created from OnInventoryListener from InventoryListFragment.java
//handles the onclick for the recycleview items
#Override
public void onInventoryClick(int position) {
}
fragmentinventory.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragments.InventoryFragment"
android:orientation="horizontal"
android:id="#+id/inventory_content">
<fragment
android:id="#+id/inventorylist_fragment"
android:name="com.example.devcash.Fragments.InventoryListFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout="#layout/fragment_inventory_list">
</fragment>
<View
style="#style/Divider"
android:layout_width="1dp"
android:layout_height="wrap_content" />
<FrameLayout
android:id="#+id/inventorylist_fragmentcontainer"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"/>
</LinearLayout>
You have to create an interface with a method which will be passed in the constructor of the adapter.
interface OnItemClickListener {
void onClick(SomeData data);
}
In constructor for recyclerView, make add a reference to this
public InventoryRecyclerViewAdapter(Context context, ArrayList<Integer> mIcon, ArrayList<String> mLabel, OnItemClickListener listener) {
this.mIcon = mIcon;
this.mLabel = mLabel;
this.context = context;
this.listener = listener;
}
In viewHolder, set an onClickListener (the one with android.* as package)
viewHolder.customLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onClick(/* PASS YOUR DATA HERE */);
});
Now when making an adapter in your activity or fragment, implement the listener and override the onClick(SomeData data) method. Now, from there you call call the fragment manager and it will work.
Already solved this problem.
Instead of this
FragmentManager fragmentManager = getFragmentManager();
I just did this
`FragmentManager fragmentManager = ((AppCompatActivity)v.getContext()).getSupportFragmenteManager(`);

RecyclerView is duplicating Alert Dialog results

I have a fragment that is suppose to display the results of my alert dialog in my RecyclerView. Every time I click the "ADD" in my dialog, it adds duplicated results to my RecyclerView. I've searched and searched but cannot seem to find what I am doing wrong. I've tried adding .clear(); but if I add that, nothing shows up in my RecyclerView at all. I've added in my adapter getItemId and getItemViewType to return position; but the items still get duplicated. I've added adapter.setData(model) followed by adapter.notifyDataSetChange(); and my RecyclerView still shows duplicated items. The app runs so I have no logcat to post. Thank you.
Model
public class SubjectsModel
{
//private long id;
private String mTitle;
private String mTeacher;
public String getmTitle()
{
return mTitle;
}
public void setmTitle(String title)
{
this.mTitle = title;
}
public String getmTeacher()
{
return mTeacher;
}
public void setmTeacher(String teacher)
{
this.mTeacher = teacher;
}
}
Fragment
public class SubjectsFrag extends DialogFragment implements
SubjectsEditor.OnAddSubjectListener
{
private static final String TAG = SubjectsFrag.class.getSimpleName();
#NonNull
Context context;
private EditText titleView, teacherView;
private String sTitle, sTeacher;
public EmptyRecyclerView recyclerView;
public RecyclerView.LayoutManager layoutManager;
public RecyclerSubAdapter recyclerSubAdapter;
public ArrayList<SubjectsModel> subMod = new ArrayList<>();
DbHelper helper;
#BindView(R.id.main_root)
ViewGroup root;
public SubjectsFrag() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_subjects, container, false);
FloatingActionButton fab = view.findViewById(R.id.fab_sub);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showDialog();
}
});
helper = new DbHelper(getActivity());
helper.getSubject();
titleView = view.findViewById(R.id.edit_subject);
teacherView = view.findViewById(R.id.edit_subject_teacher);
View emptyView = view.findViewById(R.id.empty_subject_view);
recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerSubAdapter = new RecyclerSubAdapter(getContext(), subMod);
layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(recyclerSubAdapter);
return view;
}
#Override
public void OnAddSubjectSubmit(String title, String teacher)
{
SubjectsModel model = new SubjectsModel();
model.setmTitle(title);
model.setmTeacher(teacher);
//subMod.clear();
subMod.add(model);
recyclerSubAdapter.setData(subMod);
recyclerSubAdapter.notifyDataSetChanged();
}
private void showDialog()
{
SubjectsEditor addSubjectDialog = new SubjectsEditor();
addSubjectDialog.setTargetFragment(this, 0);
addSubjectDialog.show(getFragmentManager(), null);
}
}
Adapter
public class RecyclerSubAdapter extends RecyclerView.Adapter<RecyclerSubAdapter.ViewHolder>
{
private static final String TAG = RecyclerSubAdapter.class.getSimpleName();
public List<SubjectsModel> subMod = new ArrayList<>();
private OnItemClicked onClick;
static ClickListener clickListener;
Context context;
DbHelper helper;
public RecyclerSubAdapter(Context context, ArrayList<SubjectsModel> subMod)
{
this.context = context;
this.subMod = subMod;
this.helper = new DbHelper(context);
}
#NonNull
#Override
public RecyclerSubAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.subjects_item_list, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(final RecyclerSubAdapter.ViewHolder holder, final int position)
{
SubjectsModel currentSubject = subMod.get(position);
holder.titleView.setText(currentSubject.getmTitle());
holder.teacher.setText(currentSubject.getmTeacher());
//helper.addClass(subMod.get(position));
}
public class ViewHolder extends RecyclerView.ViewHolder implements
View.OnClickListener
{
TextView titleView;
TextView teacher;
CardView cardView;
public ViewHolder(View itemView)
{
super(itemView);
titleView = itemView.findViewById(R.id.subject_subject);
teacher = itemView.findViewById(R.id.subject_teacher_text);
cardView = itemView.findViewById(R.id.card_view);
}
#Override
public void onClick(View view)
{
if (clickListener != null)
{
}
}
}
#Override
public int getItemCount()
{
if (subMod == null)
{
Log.d(TAG, "sub is null");
}
return subMod.size();
}
#Override
public long getItemId(int position)
{
return position;
}
#Override
public int getItemViewType(int position)
{
return position;
}
public interface OnItemClicked
{
void onItemClick(int position);
}
public void setOnClick(OnItemClicked onClick)
{
this.onClick = onClick;
}
public void setClickListener(ClickListener clicked)
{
RecyclerSubAdapter.clickListener = clicked;
}
public interface ClickListener
{
void itemClicked(SubjectsModel model, int position);
}
public void setData(ArrayList<SubjectsModel> data)
{
this.subMod = data;
//this.subMod.clear();
this.subMod.addAll(data);
notifyDataSetChanged();
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main_root">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.ashleighwilson.schoolscheduler.adapter.EmptyRecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="60dp"/>
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<TextView
android:id="#+id/empty_subject_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone"
android:text="#string/no_subjects"/>
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_sub"
style="#style/FAB" />
</RelativeLayout>
In OnAddSubjectSubmit() you call subMod.add(model);
and then you call recyclerSubAdapter.setData(subMod); which in turn calls this.subMod.addAll(data);.
Check it yourself. I believe it's there where you add the new item twice.
Suggestion: comment out recyclerSubAdapter.setData(subMod); from OnAddSubjectSubmit().
this.subMod = data;
this.subMod.addAll(data);
You initilize subMod by assigning data to it, and later you add data again:
this.subMod.addAll(data);

How to get clicked items from RecyclerView itemclicklistener and set it to textview?

I have one query related to RecyclerView. I want to get clicked items and set it to textview in the same layout then after that set the values to textview, update the adapter.
This is my recyclerview.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/rl_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/imageView_flag"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:src="#drawable/usa" />
<TextView
android:id="#+id/textview_currency_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1 USD(United States of America)"
android:layout_centerVertical="true"
android:textColor="#000"
android:layout_toEndOf="#+id/imageView_flag"
android:layout_marginStart="14dp" />
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view_exchange_rate"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/rl_container"/>
</RelativeLayout>
This is my fragment class:
public class ExchangeRatesFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private OnFragmentInteractionListener mListener;
private String mParam1;
private String mParam2;
RetrofitClient retrofitClient;
RestInterface service;
ArrayList<ExchangeRate> exchangeRatesArraylist;
private RecyclerView mRecyclerView;
private ExchangeRateAdapter exchangeRateAdapter;
TextView textview_currency_info;
ImageView imageView_flag;
public ExchangeRatesFragment() {}
public static ExchangeRatesFragment newInstance(String param1, String param2) {
ExchangeRatesFragment fragment = new ExchangeRatesFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_exchange_rates, container, false);
exchangeRatesArraylist = new ArrayList<>();
retrofitClient = new RetrofitClient();
service = retrofitClient.getAPIClient(WebServiceUrls.DOMAIN_MAIN);
textview_currency_info = (TextView) rootView.findViewById(R.id.textview_currency_info);
imageView_flag = (ImageView) rootView.findViewById(R.id.imageView_flag);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view_exchange_rate);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(layoutManager);
get_exchange_rate("USD");
return rootView;
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
void onFragmentInteraction(Uri uri);
}
public void get_exchange_rate(String from){
service.exchange_rate(from, new Callback<JsonElement>() {
#Override
public void success(JsonElement jsonElement, Response response) {
//this method call if webservice success
try {
JSONObject jsonObject = new JSONObject(jsonElement.toString());
final JSONArray exchange_rate = jsonObject.getJSONArray("exchange_rate");
for(int i=0; i<exchange_rate.length(); i++){
JSONObject currencyNews = exchange_rate.getJSONObject(i);
String short_name = currencyNews.getString("short_name");
String full_name = currencyNews.getString("full_name");
String flag = currencyNews.getString("flag");
String chang_value =currencyNews.getString("chang_value");
ExchangeRate currencyConverter = new ExchangeRate(short_name, full_name, flag, chang_value);
exchangeRatesArraylist.add(currencyConverter);
}
exchangeRateAdapter = new ExchangeRateAdapter(getContext(), exchangeRatesArraylist);
mRecyclerView.setAdapter(exchangeRateAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void failure(RetrofitError error) {
Toast.makeText(getActivity(),"Please check your internet connection", Toast.LENGTH_LONG ).show();
}
});
}
This is my adapter class:
public class ExchangeRateAdapter extends RecyclerView.Adapter<ExchangeRateAdapter.ViewHolder>{
private ArrayList<ExchangeRate> mArrayList;
private Context context;
private final LayoutInflater mInflater;
public ExchangeRateAdapter(Context context, ArrayList<ExchangeRate> arrayList) {
this.mInflater = LayoutInflater.from(context);
mArrayList = arrayList;
context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.exchange_rate_items, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int i) {
holder.relativeLayout.setOnClickListener(clickListener);
holder.textView_full_name.setTag(holder);
holder.textView_short_name.setText(mArrayList.get(i).getShort_name());
holder.textView_full_name.setText(mArrayList.get(i).getFull_name());
holder.textview_currency_value.setText(mArrayList.get(i).getChang_value());
Picasso.with(context).load("http://uploads/country_flag/"+ mArrayList.get(i).getFlag()).into(holder.imageView_flag);
}
private View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
ViewHolder holder = (ViewHolder) view.getTag();
int position = holder.getPosition();
ExchangeRate person = mArrayList.get(position);
String businessids = person.getFull_name();
Intent intent = new Intent(context, test.class);
intent.putExtra("businessids", businessids);
context.startActivity(intent);
}
};
#Override
public int getItemCount() {
return mArrayList.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
private TextView textView_short_name, textView_full_name, textview_currency_value;
private ImageView imageView_flag;
RelativeLayout relativeLayout;
ViewHolder(View itemView) {
super(itemView);
textView_short_name = (TextView)itemView.findViewById(R.id.textView_short_name);
textView_full_name = (TextView)itemView.findViewById(R.id.textView_full_name);
imageView_flag = (ImageView) itemView.findViewById(R.id.imageView_flag);
textview_currency_value = (TextView)itemView.findViewById(R.id.textview_currency_value);
relativeLayout = (RelativeLayout) itemView.findViewById(R.id.rl);
}
}
}
I have tried many options which published on SO but I didn't any solution. How to solve this query? When I set the onclicklistener to ViewHolder so I'm getting the position values only -1 on every item clicklistener.
A few things:
You are setting a tag on "holder.textView_full_name.setTag(holder)" while you are getting the tag from the view which was clicked (which would be the relative layout, as that is where you set the click listener (holder.relativeLayout.setOnClickListener(clickListener);)
This isn't necessary anyways.
In your click listener, call 'getAdapterPosition()', which should return what you are expecting.
Edit: Codepath has a nice overview of the RecyclerView, a little dated, but still relevant.
You can use this dependencies
implementation 'io.reactivex:rxjava:1.2.1'
implementation 'io.reactivex:rxandroid:1.2.1'
Just for example:
Reference
as with this you can click on RecyclerView
adapter.busNoItemClick().doOnNext(this::getBusNum).subscribe();
private void getBusNum(String busNo){
((TextView)findViewById(R.id.txtBusNumberStudent)).setText(busNo);
}
in adapter you have to write this:
#Override
public void onBindViewHolder(AdapterBusRouteParent.ViewHolder holder, int position) {
holder.busNumber.setOnClickListener(view -> publishSubject.onNext(busRouteParents.get(position)));
}
public Observable<String>busNoItemClick(){
return publishSubject.observeOn(AndroidSchedulers.mainThread());
}
Hope this might help you.
One way would be to have a
Variable which stores the selected item,
Set OnClickistener to the ItemView,
In the OnClickListener, set the SELECTED_INDEX as getAdapterPosition() and notify the adapter.
In the onBindViewHolder method, check if current position is equal to SELECTED_INDEX and implement the required steps.
:
int SELECTED_INDEX = 0;
public void setSelectedItemIndex(int position){
SELECTED_INDEX = position;
/*if(adapterCallback!=null) { //If you have a callback interface
adapterCallback.onItemClick(position);
}*/
notifyDataSetChanged();
}
Holder Class:
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
//Item Declarations
public MyViewHolder(View itemView) {
super(itemView);
//View Binding
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v){
if(v==itemView){
setSelectedItemIndex(getAdapterPosition());
}
}
}
In onBindViewHolder method:
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
if(position==SELECTED_INDEX){
//Implement your steps
}
else{
//Default Value
}
}
Hope it helps!

Categories

Resources