I'm using a RecyclerView and populating data from the database and storing it into arrayLists. i've also added an onLongClickListener() to the recycler view which removes the long clicked row. Everything works fine but when I delete the last the app crashes and i get Java.Lang.IndexOutOfBoundsException index:0 size:0.
here's my code
public class MainActivity extends AppCompatActivity implements AlarmRecyclerViewInterface {
FloatingActionButton mAlarmAddButton;
RecyclerView mRecyclerView;
SQLiteDatabase db;
AlarmsDBhelperClass mAlarmsDBhelperClass;
ArrayList<String> nameArrayList = new ArrayList<>();
ArrayList <String> modeArrayList = new ArrayList<>();
ArrayList<String> repeatArrayList = new ArrayList<>();
ArrayList<String> hoursArrayList = new ArrayList<>();
ArrayList<String> minArrayList = new ArrayList<>();
Switch mSwitch;
AlarmAdapter alarmAdapter = new AlarmAdapter(hoursArrayList,minArrayList,modeArrayList,repeatArrayList,nameArrayList,this);
ImageView emptyImageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//Initializing RecyclerView, DatabaseHelperClass, FAB button, The ON OFF switch & the empty ImageView
mAlarmsDBhelperClass = new AlarmsDBhelperClass(getApplicationContext());
mAlarmAddButton = findViewById(R.id.btnAlarmADD);
mRecyclerView = findViewById(R.id.alarmList);
mSwitch = findViewById(R.id.switchONOFF);
emptyImageView = findViewById(R.id.empty_view);
//DividerItemDecoration class is used for getting a vertical line between rows of RecyclerView
DividerItemDecoration itemDecoration = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(itemDecoration);
//Getting a writable reference of the Database.
db = mAlarmsDBhelperClass.getWritableDatabase();
//Retrieving values from the database and storing them in custom ArrayLists
boolean isDataEmpty = getAlarm(db);
//Checking if our arrayList is empty? if yes then display some empty list text or an image
if (!isDataEmpty){
mRecyclerView.setVisibility(View.GONE);
emptyImageView.setImageResource(R.drawable.no_alarm_black_white);
emptyImageView.setVisibility(View.VISIBLE);
}
else {
mRecyclerView.setVisibility(View.VISIBLE);
emptyImageView.setVisibility(View.GONE);
}
//FAB Event handling
mAlarmAddButton.setImageResource(R.drawable.addalarm);
mAlarmAddButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent mIntent = new Intent(getApplicationContext(), AddAlarm.class);
startActivity(mIntent);
}
});
//Warping up with the recyclerView
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
mRecyclerView.setAdapter(alarmAdapter);
mRecyclerView.setHasFixedSize(true);
}
public boolean getAlarm(SQLiteDatabase db) {
Cursor cursor = db.rawQuery("SELECT * FROM alarms", new String[]{});
boolean rowExists;
if (cursor.moveToFirst()) {
do {
nameArrayList.add(cursor.getString(2));
modeArrayList.add(cursor.getString(3));
repeatArrayList.add(cursor.getString(4));
hoursArrayList.add(Integer.toString(cursor.getInt(5)));
minArrayList.add(Integer.toString(cursor.getInt(6)));
rowExists = true;
} while (cursor.moveToNext());
}else {
rowExists = false;
}
cursor.close();
return rowExists;
}
//RecyclerView's onClick()
#Override
public void onItemClick(int position) {
Toast.makeText(this, "Alarm Clicked !", Toast.LENGTH_SHORT).show();
}
//RecyclerView's onLongClick()
#Override
public void onLongItemClick(int position) {
hoursArrayList.remove(position);
//Updating the recyclerView
alarmAdapter.notifyItemRemoved(position);
//Deleting the row from the database
db.delete("alarms","hours=?",new String[]{hoursArrayList.get(position)});
Toast.makeText(this,"Alarm Deleted !", Toast.LENGTH_SHORT).show();
}
}
here's my RecyclerView Adapter
public class AlarmAdapter extends RecyclerView.Adapter<AlarmAdapter.AlarmView> {
//Variables for the main recycler view
private ArrayList<String> hoursArrayList;
private ArrayList<String> minArrayList;
private ArrayList<String> modeArrayList;
private ArrayList<String> repeatArrayList;
private ArrayList<String> nameArrayList;
private AlarmRecyclerViewInterface mInterface;
public AlarmAdapter(ArrayList<String> hours,ArrayList<String> mins,ArrayList<String> mode,ArrayList<String> repeat,ArrayList<String> name,AlarmRecyclerViewInterface mInterface){
this.hoursArrayList = hours;
this.minArrayList = mins;
this.modeArrayList = mode;
this.nameArrayList = name;
this.repeatArrayList = repeat;
this.mInterface = mInterface;
}
#NonNull
#Override
public AlarmView onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view = layoutInflater.inflate(R.layout.alarm_profile,parent,false);
return new AlarmView(view);
}
#Override
public void onBindViewHolder(#NonNull AlarmView holder, int position) {
if(Integer.parseInt(hoursArrayList.get(position)) < 10 ){
holder.hours.setText("0"+hoursArrayList.get(position));
}else {
holder.hours.setText(hoursArrayList.get(position));
}
if (Integer.parseInt(minArrayList.get(position)) < 10){
holder.mins.setText("0"+minArrayList.get(position));
}else {
holder.mins.setText(minArrayList.get(position));
}
holder.repeat.setText(repeatArrayList.get(position));
holder.mode.setText(modeArrayList.get(position));
holder.name.setText(nameArrayList.get(position));
}
#Override
public int getItemCount() {
return hoursArrayList.size();
}
/*ItemTouchHelper.SimpleCallback itemTouchHelperCallback = new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
nameArrayList.remove(viewHolder.getAdapterPosition());
modeArrayList.remove(viewHolder.getAdapterPosition());
repeatArrayList.remove(viewHolder.getAdapterPosition());
hoursArrayList.remove(viewHolder.getAdapterPosition());
minArrayList.remove(viewHolder.getAdapterPosition());
}
};*/
public class AlarmView extends RecyclerView.ViewHolder{
TextView hours,mins,repeat,name,mode;
public AlarmView(#NonNull View itemView) {
super(itemView);
hours = itemView.findViewById(R.id.txtHOUR);
mins = itemView.findViewById(R.id.txtMins);
repeat = itemView.findViewById(R.id.txtRepeatDays);
name = itemView.findViewById(R.id.txtName);
mode = itemView.findViewById(R.id.txtMode);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mInterface.onItemClick(getAdapterPosition());
}
});
itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
mInterface.onLongItemClick(getAdapterPosition());
return true;
}
});
}
}
}
Thanks for the help!
Crash :- IndexOutOfBoundsException
Reason :- You removed data from the list and after that, you again fetching this value from the list to remove data from the database at that time it will crash because it has no value as you deleted data.
Solution :- You can delete first from the database and after that remove from your list.
Example :-
Replace below onLongClick() Override method in your class.
//RecyclerView's onLongClick()
#Override
public void onLongItemClick(int position) {
// Best way to remove data from list
if(hoursArrayList != null && hoursArrayList.size() > 0){
//Deleting the row from the database
db.delete("alarms","hours=?",new String[]{hoursArrayList.get(position)});
//Delete from your list if you successfully removed data from your database.
hoursArrayList.remove(position);
//Updating the recyclerView
if(alarmAdapter){
alarmAdapter.notifyItemRemoved(position);
}
//Message to show User.
Toast.makeText(this,"Alarm Deleted !", Toast.LENGTH_SHORT).show();
}
}
Related
So my problem is that.. why does the isChecked method not working.
My first guess to my problem would be im declaring the wrong array?
My second guess would be I lack something to call or missing something out?
the goal of my code here is to create a collector in firebase and then record it in the database of the collector by which the user chose from the multiple selected job orders
public class MainActivity extends AppCompatActivity {
private List<Model> mModelList;
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
Button mjobOrderBtn;
FirebaseAuth fAuth;
FirebaseFirestore fStore;
String jobId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recyclerview);
mjobOrderBtn = findViewById(R.id.jobOrderBtn);
mRecyclerView = findViewById(R.id.recycler_view);
mAdapter = new RecyclerViewAdapter(getListData());
LinearLayoutManager manager = new LinearLayoutManager(MainActivity.this);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setAdapter(mAdapter);
fAuth = FirebaseAuth.getInstance();
fStore = FirebaseFirestore.getInstance();
jobId = fAuth.getCurrentUser().getUid();
DocumentReference documentReference = fStore.collection("job order").document(jobId);
mjobOrderBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mRecyclerView.isChecked()){
}
}
});
}
private List<Model> getListData() {
mModelList = new ArrayList<>();
mModelList.add(new Model("Flat Tire "));
mModelList.add(new Model("Towing "));
mModelList.add(new Model("Battery "));
mModelList.add(new Model("Empty Gas "));
return mModelList;
}
}
RecyclerViewAdaptor.java
class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
private List<Model> mModelList;
public RecyclerViewAdapter(List<Model> modelList) {
mModelList = modelList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_itemrow, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
final Model model = mModelList.get(position);
holder.textView.setText(model.getText());
holder.view.setBackgroundColor(model.isSelected() ? Color.CYAN : Color.WHITE);
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
model.setSelected(!model.isSelected());
holder.view.setBackgroundColor(model.isSelected() ? Color.CYAN : Color.WHITE);
}
});
}
#Override
public int getItemCount() {
return mModelList == null ? 0 : mModelList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private View view;
private TextView textView;
private MyViewHolder(View itemView) {
super(itemView);
view = itemView;
textView = itemView.findViewById(R.id.text_view);
}
}
}
Also here's the model class
Model.java
public class Model {
private String text;
private boolean isSelected = false;
public Model(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
public boolean isSelected() {
return isSelected;
}
}
you need to create checkbox inside view item layout for each item in your array. Here is an example
you can get your order list with a defined method inside adapter class. Something like this:
public List<Model> getSelectedItems(){
List<Model> results = new ArrayList<Model>();
for(model: mModelList){
if(model.isSelected()){
results.add(model);
}
}
return results;
}
And inside button order click method, just get it out:
mjobOrderBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
List<Model> orderList = mAdapter.getSelectedItems();
}
});
I have added cart image in my Adapter class but whenever I click on the button always get the last element from the list. Here is my adapter class and activity class.
Details are perfectly fetched from firebase and Log file showing list of menu.
Here is my MenuAdapter.java class.
public class MenuAdapter extends RecyclerView.Adapter<MenuAdapter.MenuViewHolder> {
private Context mCtx;
private List<Menu> menuList;
private ItemClickEvent itemclick;
public MenuAdapter(Context mCtx, List<Menu> menuList, ItemClickEvent itemclick) {
this.mCtx = mCtx;
this.menuList = menuList;
this.itemclick = itemclick;
}
#NonNull
#Override
public MenuViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i)
{
View view = LayoutInflater.from(mCtx).inflate(R.layout.menu_list, viewGroup, false);
return new MenuViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final MenuViewHolder menuViewHolder, final int i) {
final Menu menu = menuList.get(i);
menuViewHolder.itemName.setText(menu.itemName);
menuViewHolder.itemPrice.setText(menu.itemPrice);
menuViewHolder.addCart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
itemclick.imageClicked(menu);
}
});
}
#Override
public int getItemCount() {
return menuList.size();
}
public class MenuViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView itemName, itemPrice;
#SuppressLint("StaticFieldLeak")
ImageView addCart;
MenuViewHolder(#NonNull View itemView) {
super(itemView);
itemName = itemView.findViewById(R.id.itemName);
itemPrice = itemView.findViewById(R.id.itemPrice);
addCart = itemView.findViewById(R.id.menuAddCart);
//addCart.setOnClickListener(this);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
}
}
}
and this MenuActivity.java class
public class MenuActivity extends AppCompatActivity implements ItemClickEvent
{
private ActionBar toolbar;
List<Menu> menuList;
RecyclerView recyclerView;
MenuAdapter adapter;
DatabaseReference databaseReference;
ProgressBar progressBar;
Menu menu;
int foodId = 1;
int cat;
String id,itemName, itemPrice;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
Intent intent = getIntent();
final String category = intent.getStringExtra("cat_id");
final String catName = intent.getStringExtra("cat_name");
toolbar = getSupportActionBar();
toolbar.setTitle(catName);
cat = Integer.parseInt(category) - 1;
menuList = new ArrayList<>();
recyclerView = findViewById(R.id.menu_recycler);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new MenuAdapter(this, menuList,this);
recyclerView.setAdapter(adapter);
ImageView addTCart = findViewById(R.id.menuAddCart);
progressBar = findViewById(R.id.progressBarLoading);
databaseReference = FirebaseDatabase.getInstance().getReference("foods/" + cat + "/menu-items");
// fetchMenu(category);
progressBar.setVisibility(View.VISIBLE);
databaseReference.addListenerForSingleValueEvent(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
progressBar.setVisibility(View.GONE);
if (dataSnapshot.exists()) {
for (DataSnapshot wallpaperSnapshot : dataSnapshot.getChildren()) {
id = wallpaperSnapshot.getKey();
itemName = wallpaperSnapshot.child("name").getValue(String.class);
itemPrice = wallpaperSnapshot.child("price").getValue(String.class);
menu = new Menu(id, itemName, itemPrice, category);
menuList.add(menu);
Log.d("FOOD-DETAIL", String.valueOf(menu));
}
adapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void imageClicked(Menu m) {
new Database(getApplicationContext()).addToCart(new Order(
Integer.parseInt(id),
menu.getItemName(),
"1",
menu.getItemPrice()
));
foodId += 1;
Toast.makeText(getBaseContext(), itemName+" added to cart", Toast.LENGTH_SHORT).show();
}
#Override
public void viewClicked() {
}
}
Hello try making these changes in imageClicked() in MenuActivity
#Override
public void imageClicked(Menu m) {
new Database(getApplicationContext()).addToCart(new Order(
m.getId(),
m.getItemName(),
"1",
m.getItemPrice()
));
foodId += 1;
Toast.makeText(getBaseContext(), itemName+" added to cart", Toast.LENGTH_SHORT).show();
}
There should be more efficient way to set listener. Just set that listener (same way as it is now) in constructor of MenuViewHolder and assign to this. And in method onClick - check R.id of view and if it is addCart instead of calling itemclick.imageClicked(menu) just call item.click.imageClicked(getAdapterPosition())
This because onBindViewHolder() is calling multiple times and you will still create new listener. But in constructor you create that listener only if you need new MenuViewHolder and use the actual position of adapter.
I'm seeking help on how to load a data stored in a Firebase Database into a recyclerview.
The below screenshot indicates how I would like for the data to be structured when loaded into the recyclerview.
I am able to access the data from individual paths such as "Upcoming/Events/03/23" using the addEventListener but unable to load dynamically into a recyclerview in the format above.
See Code below that I have below to load the children under the different nodes, but i'm able to load it into the recyclerview
private ListView mUserList;
private ArrayList<String> mUpcomingList = new ArrayList<>();
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_expandable_list_item_1,mUpcomingList);
mUserList.setAdapter(arrayAdapter);
String CurrentString = date.toString().trim();
StringTokenizer tokens = new StringTokenizer(CurrentString, "/");
String first = tokens.nextToken();
String second = tokens.nextToken();
mDatabase = FirebaseDatabase.getInstance().getReference().child("Upcoming/Events").child(first);
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
Public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG,"Listing children");
for (DataSnapshot child: dataSnapshot.getChildren()) {
mUpcomingList.add(child.getKey());
arrayAdapter.notifyDataSetChanged();
}
Your help is appreciated.
when you used then you make recyclerview adatper and bind this adapter into a recycler view . used below code for display firebase all the data and change according your need and make changes.
RecyclerView Adapter::
public class DisplayAllData extends RecyclerView.Adapter<DisplayAllData.ItemViewHolder>{
private List<User> mUserLsit=new ArrayList<>();
private Context mContext;
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout,parent,false);
return new ItemViewHolder(view);
}
public DisplayAllData(Context mContext,List<User> mUserLsit) {
this.mContext=mContext;
this.mUserLsit = mUserLsit;
}
#Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
User user=mUserLsit.get(position);
holder.mTvName.setText(user.name);
holder.mTvEmail.setText(user.email);
holder.mTvPwd.setText(user.pwd);
}
#Override
public int getItemCount() {
return mUserLsit.size();
}
public class ItemViewHolder extends RecyclerView.ViewHolder {
TextView mTvName,mTvEmail,mTvPwd;
public ItemViewHolder(View itemView) {
super(itemView);
mTvEmail=itemView.findViewById(R.id.rlTvEmail);
mTvName=itemView.findViewById(R.id.rlTvName);
mTvPwd=itemView.findViewById(R.id.rlTvPwd);
}
}
}
In Adapter take a simple layout and make three textview control and bind data into that.
then after take activity layout and define recycler view in xml. then after used below code to read firebase database record and display recyclerview.
public class DisplayActivity extends AppCompatActivity {
private RecyclerView mRvData;
private DisplayAllData allDataAdapter;
private DatabaseReference mDatabase;
private TextView mTvEmpty;
private FirebaseDatabase mFirebaseInstance;
private List<User> mUserList = new ArrayList<>();
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.display_data);
initView();
}
private void initView() {
mFirebaseInstance = FirebaseDatabase.getInstance();
mDatabase = mFirebaseInstance.getReference("usersDb/UserTable");
mRvData = findViewById(R.id.rvData);
mTvEmpty = findViewById(R.id.dlTvEmpty);
mRvData.setLayoutManager(new LinearLayoutManager(this));
mDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mUserList.clear();
for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()) {
User user = dataSnapshot1.getValue(User.class);
mUserList.add(user);
}
allDataAdapter = new DisplayAllData(DisplayActivity.this, mUserList);
mRvData.setAdapter(allDataAdapter);
allDataAdapter.notifyDataSetChanged();
if (mUserList.isEmpty())
mTvEmpty.setVisibility(View.VISIBLE);
else
mTvEmpty.setVisibility(View.GONE);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
You have to use FirebaseRecyclerAdapter,
as
FirebaseRecyclerAdapter<Model, ViewHolder> Adapter = new FirebaseRecyclerAdapter<Model, ViewHolder>(
Model.class, //Name of model class
R.layout.row, //Row layout to show data
viewHolder.class, //Name of viewholder class
mDatabaseRef // Database Refernce
) {
#Override
protected void populateViewHolder(VieHolder viewHolder, Model model, int position) {
//Your Method to load Data
}
};
RecyclerView.setAdapter(Adapter);
For this you have to create two other classes, One is viewholder ( to display data) and second model class ( refers to name of nodes from where you are fetching data ).
final DatabaseReference cartListRef = FirebaseDatabase.getInstance().getReference().child("Cart List");
FirebaseRecyclerOptions<Cart> options = new FirebaseRecyclerOptions.Builder<Cart>()
.setQuery(cartListRef.child("User View")
.child(Prevalent.currentOnlineUser.getPhoneNumber())
.child("Products"), Cart.class).build();
FirebaseRecyclerAdapter<Cart, CartViewHolder> adapter =
new FirebaseRecyclerAdapter<Cart, CartViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull CartViewHolder holder, int position, #NonNull final Cart model) {
holder.txtProductQuantity.setText("Quantity = " + model.getQuantity());
holder.txtProductName.setText(model.getPname());
holder.txtProductPrice.setText("Price = " + model.getPrice() + "৳");
int oneTypeProductPrice = ((Integer.valueOf(model.getPrice()))) * Integer.valueOf(model.getQuantity());
overTotalPrices = overTotalPrices + oneTypeProductPrice;
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CharSequence options[] = new CharSequence[]
{
"Edit",
"Remove"
};
AlertDialog.Builder builder = new AlertDialog.Builder(CartActivity.this);
builder.setTitle("Cart Options");
builder.setItems(options, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int i) {
if (i == 0){
Intent intent = new Intent(CartActivity.this, ProductDetailsActivity.class);
intent.putExtra("pid", model.getPid());
startActivity(intent);
}
if (i == 1){
cartListRef.child("User View")
.child(Prevalent.currentOnlineUser.getPhoneNumber())
.child("Products")
.child(model.getPid())
.removeValue()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()){
Toast.makeText(CartActivity.this,"Item removed successfully.",Toast.LENGTH_LONG).show();
Intent intent = new Intent(CartActivity.this, HomeActivity.class);
startActivity(intent);
}
}
});
}
}
});
builder.show();
}
});
}
#NonNull
#Override
public CartViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cart_items_layout, parent, false);
CartViewHolder holder = new CartViewHolder(view);
return holder;
}
};
recyclerView.setAdapter(adapter);
adapter.startListening();
}
I created a recyclerview that takes data from Firebase. I have two arrays that are sent to the adapter to be used in the items. I've implemented a search filter. This works for the first array, but the second one is always in the starting position. How can I get the second array in the same position as the first filter? Thank you
MainActivity
public class FriendActivity3 extends AppCompatActivity
//implements FriendHoldAdapter3.ItemClickListener{
FriendHoldAdapter3 adapter;
RecyclerView recyclerView;
ArrayList<FriendItem> username;
ArrayList<String> uid, url;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_friend2);
SearchView search = (SearchView) findViewById(R.id.ciao);
recyclerView = (RecyclerView) findViewById(R.id.friend_list2);
//recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
final DatabaseReference mPostReference = FirebaseDatabase.getInstance().getReference().child("user-profile");
mPostReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
username = new ArrayList<>();
uid = new ArrayList<String>();
url = new ArrayList<String>();
for (DataSnapshot data : dataSnapshot.getChildren()){
final FriendItem friendItem = data.getValue(FriendItem.class);
final String friendItem2 = data.getKey();
username.add(friendItem);
uid.add(friendItem2);
adapter = new FriendHoldAdapter3(getApplicationContext(), username, uid, url);
//adapter.setClickListener(FriendActivity3.this);
recyclerView.setAdapter(adapter);
/**
adapter = new FriendHoldAdapter2(FriendActivity2.this, username, uid);
adapter.setClickListener(FriendActivity2.this);
recyclerView.setAdapter(adapter);
**/
final List<FriendItem> filteredModelList = filter(username, " ");
adapter.setFilter(filteredModelList);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}});
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
if (newText.equals("")){
newText = " ";
}
if (newText.equals("View All")){
newText = "";
}
final List<FriendItem> filteredModelList = filter(username, newText);
adapter.setFilter(filteredModelList);
return true;
}
});
private List<FriendItem> filter(List<FriendItem> models, String query) {
query = query.toLowerCase();final List<FriendItem> filteredModelList = new ArrayList<>();
for (FriendItem model : models) {
final String text = model.username.toLowerCase();
if (text.contains(query)) {
filteredModelList.add(model);
}
}
return filteredModelList;
}}
Adapter
public class FriendHoldAdapter3 extends RecyclerView.Adapter<FriendHoldAdapter3.ViewHolder> {
private List<FriendItem> mData_username = Collections.emptyList();
private List<String> mData_uid = Collections.emptyList();
private List<String> mData_url = Collections.emptyList();
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
public FriendHoldAdapter3(Context context, List<FriendItem> data_username, List<String> data_uid, List<String> data_url) {
this.mInflater = LayoutInflater.from(context);
this.mData_username = data_username;
this.mData_uid = data_uid;
this.mData_url = data_url;
}
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.friend_item, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
// binds the data to the textview in each row
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
FriendItem username = mData_username.get(position);
String uid = mData_uid.get(position);
holder.myTextView.setText(username.username);
holder.uid_txt.setText(uid);
}
// total number of rows
#Override
public int getItemCount() {
return mData_username.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView myTextView, uid_txt;
public ViewHolder(final View itemView) {
super(itemView);
myTextView = (TextView) itemView.findViewById(R.id.friend_item_name);
uid_txt = (TextView) itemView.findViewById(R.id.friend_item_uid);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(itemView.getContext(),mData_uid.get(getAdapterPosition()), Toast.LENGTH_SHORT).show();
if (uid_txt.getText().toString()!=null | !uid_txt.getText().toString().equals("") ){
Intent intent = new Intent(itemView.getContext(), AccountPubblic.class);
//MANDARE TESTO A AccountPubblic
intent.putExtra(AccountPubblic.EXTRA_UID, uid_txt.getText().toString());
itemView.getContext().startActivity(intent);
}
}
});
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// convenience method for getting data at click position
public FriendItem getItem(int id) {
return mData_username.get(id);
}
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
// allows clicks events to be caught
public void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
public void setFilter(List<FriendItem> countryModels) {
mData_username = new ArrayList<>();
mData_username.addAll(countryModels);
notifyDataSetChanged();
}}
I have a RecyclerView list of CardView items. I then use a simple filter method with a SearchView widget to filter the list. When I then click on a filtered CardView to launch a CardViewDetails Activity, the UI is showing the CardView from the original List and not the filtered List. For example, I have a list of twenty items in the original List. When I enter a search constraint the filtered List correctly shows three CardViews in the RecyclerView. When I click on the third CardView in the List, the UI returns the third CardView from the original List and not the third CardView from the filtered List. What am I missing here?
Adapter:
public class MyRecylerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<ListItem> mListItems, filteredList;
Context mContext;
private RecyclerItemClickListener recyclerItemClickListener;
private RecyclerView mRecyclerView;
/**********************************************************/
private String searchString = "";
/**********************************************************/
public MyRecylerAdapter(Context context, List<ListItem> listItems) {
this.mContext = context;
this.mListItems = listItems;
this.filteredList = new ArrayList<>();
this.filteredList.addAll(this.mListItems);
}
// RecyclerItemClickListener is the public interface file used to reach the MainActivity
public void setOnItemClickListener(RecyclerItemClickListener recyclerItemClickListener) {
this.recyclerItemClickListener = recyclerItemClickListener;
}
// Get the Item's position.
public ListItem getItem(int position) {
return filteredList.get(position);
}
#Override
public int getItemCount() {
if (filteredList.size() >0) {
return filteredList.size();
}
else {
return mListItems.size();
}
}
public void setFilter(List<ListItem> listItems, String searchString) {
// Note: the String is to get s.toString() from the Main Activity SearchView.
filteredList = new ArrayList<>();
filteredList.addAll(listItems);
this.searchString = searchString;
notifyDataSetChanged();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_contact_item, parent, false);
final ItemHolder itemHolder = new ItemHolder(view);
// Attach a Click listener to the items's (row) view.
// itemView is from the ItemHolder() below.
// onItemClick is the click method in MainActivity.
itemHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int adapterPos = itemHolder.getAdapterPosition(); // get the item position.
if (adapterPos != RecyclerView.NO_POSITION) {
if (recyclerItemClickListener != null) {
// pass the item to the Main Activity
// through the RecyclerItemClickListener file and its
// public interface.
recyclerItemClickListener.onItemClick(itemHolder.itemView,adapterPos);
}
}
}
});
return itemHolder;
}
private static class ItemHolder extends RecyclerView.ViewHolder {
private TextView cardBlankText2;
private ItemHolder(View itemView) {
super(itemView);
cardBlankText2 = (TextView) itemView.findViewById(R.id.cardBlankText2);
}
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
final ListItem listItem = filteredList.get(position);
final ItemHolder itemHolder = (ItemHolder) holder;
itemHolder.cardBlankText2.setText(listItem.getTodo());
}
Activity:
public class MainActivity extends AppCompatActivity implements
RecyclerItemClickListener {
private List<ListItem> allList = new ArrayList<>();
private RecyclerView mRecyclerView;
private SQLiteDB sqLiteDB;
private MyRecylerAdapter adapter;
private CardView cardview;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sqLiteDB = SQLiteDB.getInstance(this);
mRecyclerView = (RecyclerView)findViewById(R.id.list_recyclerview);
final LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(layoutManager);
allList = sqLiteDB.getAllDBItems();
adapter = new MyRecylerAdapter(this, allList);
adapter.setOnItemClickListener(this);
mRecyclerView.setAdapter(adapter);
}
#Override
public void onItemClick(View view, int position) {
cardview = (CardView) view;
cardview.setEnabled(false);
// Create a new intent to send data from this MainActivity to the CardViewDetails
// Activity.
Intent intent = new Intent(this,CardViewDetails.class);
ListItem listItem = adapter.getItem(position);
// Add the item object to the Intent. The item object can be used because the
// model class implements Parcelable so it holds all of the getters
// that can be snagged in the next Activity with the
// getParcelableExtra method.
intent.putExtra("item",listItem);
intent.putExtra("position",position);
startActivity(intent);
finish();
}
// SearchView
final EditText mSearchEditText = (EditText) mSearchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
mSearchEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
final ArrayList<ListItem> filteredModelList = filter(allList, s.toString());
if (!mSearchView.isIconified() && filteredModelList.size() == 0) {
Toast.makeText(MainActivity.this, "Not Found", Toast.LENGTH_SHORT).show();
// re-load the list so the Adapter refreshes the RecyclerView list View.
adapter.clear();
adapter.addAll(allList);
} else if (!mSearchView.isIconified() && filteredModelList.size() > 0) {
adapter.setFilter(filteredModelList, s.toString());
mRecyclerView.scrollToPosition(0);
}
}
}
});
private ArrayList<ListItem> filter(List<ListItem> models, String query) {
query = query.toLowerCase();
final ArrayList<ListItem> filteredModelList = new ArrayList<>();
for (ListItem listItem : models) {
final String text = listItem.getTodo().toLowerCase();
final String text2 = listItem.getNote1().toLowerCase();
final String text3 = listItem.getNote2().toLowerCase();
if (text.contains(query) || text2.contains(query) ||
text3.contains(query)) {
filteredModelList.add(listItem);
}
}
return filteredModelList;
}
RecyclerItemClickListener:
public interface RecyclerItemClickListener {
void onItemClick(View view, int position);
}
CardViewDetails:
public class CardViewDetails extends AppCompatActivity {
private int position;
private SQLiteDB helper;
List<ListItem> listItems;
private CardView cardview;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details);
final CardView cardView = (CardView) findViewById(R.id.dets);
// Create a variable for the skychill footer text.
final TextView skychilltext5;
// A db helper instance is needed for the removeItem() below
// when the user Longclicks the skycard for deletion.
helper = new SQLiteDB(this);
// Get the position of the clicked on R. list CardView from
// the MainActivity's intent bundle.
Bundle extras = getIntent().getExtras();
if (extras != null) {
// get the CardView item using the int position from the
// MainActivity's onItemClick() and the putExtra in the intent.
position = extras.getInt("position",0); // 0 is default value
}
cb2 = (TextView) findViewById(R.id.cb2);
helper = new SQLiteDB(this);
listItems = new ArrayList<>();
listItems = helper.getAllDBItems();
cb2.setText(listItems.get(position).getTodo());
...
}
After applying filter the sql DB (getAllDBItems ) data remain same. You are passing only position to CardViewDetail. And the sql data is of original list.
You should pass your ListItem as parcelable to CardViewDetails instead of position. your problem will be solved.