So, I have a listview and an adapter that populates the data into the listview.
Each row in the list item has a checkbox. And there is a button in the fragment that allows deleting the checked items from the database using their id.
However, I want this to happen:
I have achieved all 3 of the above steps. But I am struggling with the last one. I could remove a single item from the list view when clicked on the image button but the problem is with multiple items.
CODE FOR ADAPTER:
public class ReqFoodAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener {
private Activity activity;
private ArrayList<HashMap<String, String>> data;
// the arraylist that holds the data of the checked items
private ArrayList<String> checkedList = new ArrayList<String>();
private static LayoutInflater inflater=null;
Bitmap image,receivedBitmap;
public ReqFoodAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// initializing each item in the arraylist
for(int i = 0; i < data.size(); i++ ){
checkedList.add(i,"0");
}
}
//method to return the arraylist to the fragment
public ArrayList<String> getCheckedList(){
return checkedList;
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View vi = convertView;
if(convertView == null)
vi = inflater.inflate(R.layout.list_row_req_food, null);
TextView fid = vi.findViewById(R.id.lv_req_id);
TextView name = vi.findViewById(R.id.item_name);
TextView qty = vi.findViewById(R.id.item_req_qty);
TextView ngoAdd = vi.findViewById(R.id.ngo_address);
TextView resName = vi.findViewById(R.id.ngoName);
ImageView type = vi.findViewById(R.id.type);
ImageView thumb_image = vi.findViewById(R.id.ngo_image);
ImageView btn_req_confirm = vi.findViewById(R.id.btn_req_confirm);
//checkbox in each row
CheckBox checkBox = vi.findViewById(R.id.chkThisRequest);
checkBox.setOnCheckedChangeListener(this);
HashMap<String, String> food = new HashMap<String, String>();
food = data.get(position);
checkBox.setTag(position + "," + food.get(FoodRequests.KEY_ID));
fid.setText(food.get(FoodRequests.KEY_ID));
name.setText(food.get(FoodRequests.KEY_NAME));
qty.setText(food.get(FoodRequests.KEY_REQ_QTY) + " kg");
ngoAdd.setText(food.get(FoodRequests.KEY_NGO_ADD));
resName.setText(food.get(FoodRequests.KEY_NGO_NAME));
if(food.get(FoodRequests.KEY_TYPE).equals("Veg"))
type.setImageResource(R.drawable.veg);
else if(food.get(FoodRequests.KEY_TYPE).equals("Non-Veg"))
type.setImageResource(R.drawable.non_veg);
btn_req_confirm.setTag(position + "," + food.get(FoodRequests.KEY_ID));
btn_req_confirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String arrayTag[] = ((String) view.getTag()).split(",");
String key = arrayTag[1];
//Update the database using key here
int pos = Integer.parseInt(arrayTag[0]);
data.remove(pos);
ReqFoodAdapter.this.notifyDataSetChanged();
}
});
return vi;
}
// onchecked change of the checkbox, change the checkedList value to the id
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
String arrayTag[] = ((String) compoundButton.getTag()).split(",");
String key = arrayTag[1];
int pos = Integer.parseInt(arrayTag[0]);
if(b) {
checkedList.set(pos, key);
}else{
checkedList.set(pos,"0");
}
}
// method to remove item
public void removeItem(int index){
data.remove(ReqFoodAdapter.this.getItem(index));
}
public void updateListView(){
notifyDataSetChanged();
}
}
* CODE FOR FRAGMENT*:
public class FoodRequests extends Fragment {
public FoodRequests() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootview = inflater.inflate(R.layout.fragment_food_requests, container, false);
lvReqFood = rootview.findViewById(R.id.list_req_food);
arrListReqFood = new ArrayList<HashMap<String, String>>();
new LoadReqFood().execute();
btnConfirmAll = rootview.findViewById(R.id.btnConfirmAll);
// button confirm multiple reuqests
btnConfirMultiple = rootview.findViewById(R.id.btnConfirmMultiple);
return rootview;
}
private class LoadReqFood extends AsyncTask<String, String, String >{
ProgressDialog loadingRequests;
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
loadingRequests.dismiss();
adapter = new ReqFoodAdapter(getActivity(), arrListReqFood);
lvReqFood.setAdapter(adapter);
btnConfirMultiple.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// get the checked list
ArrayList<String> checkedList = adapter.getCheckedList();
try {
for (int i = 0; i < checkedList.size(); i++){
temp.put(String.valueOf(i + 1), checkedList.get(i));
}
joAllRequests.put("requests",temp.toString());
}catch (JSONException j){
j.printStackTrace();
}
// update the database using each of the id of the list
new UpdateRequest().execute();
}
});
}
}
private class UpdateRequest extends AsyncTask<String, String, String>{
String msg;
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
ArrayList<String> checkedList = adapter.getCheckedList();
for (int i = 0; i < checkedList.size(); i++){
if(!checkedList.get(i).equals("0")) {
String arrayTag[] = checkedList.get(i).split(",");
int pos = Integer.parseInt(arrayTag[0]);
adapter.removeItem(pos);
}
}
adapter.updateListView();
}
}
}
So, the data gets loaded, selected items get updated, but when I wish to remove the item from the listview, it throws an ArrayIndexOutOfBound exception. It is because, what I have figured out when one item is removed from the data, its position gets altered and when I pass another item to be removed with a given position, it throws an error.
How to go about this?
Or are there any better approaches to my problem?
To avoid the problem of position change, just revese the direction of for-loop, so the code like this:
ArrayList<String> checkedList = adapter.getCheckedList();
for (int i = checkedList.size() - 1; i => 0; i--){
if(!checkedList.get(i).equals("0")) {
String arrayTag[] = checkedList.get(i).split(",");
int pos = Integer.parseInt(arrayTag[0]);
adapter.removeItem(pos);
}
}
adapter.resetCheckedList();
adapter.updateListView();
The checklist also need to reset after removed items, so constructor of the adpater can be changed like this:
public ReqFoodAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
resetCheckedList();
}
public void resetCheckedList(){
checkedList.clear();
// initializing each item in the arraylist
for(int i = 0; i < data.size(); i++ ){
checkedList.add(i,"0");
}
}
Hope that helps!