Prototype
Prototype

Reputation: 568

When using arrayList.remove(position) the application crashes

I am using geofire to populate my recyclerview working fine onkeyEnter but when the onKeyExited call my application is crashes please help me here is my code.

 private void Geofireinit() {
    started = true;
    GeoQuery geoQuery = fire.queryAtLocation(new GeoLocation(20.887715, 77.757623), 50);
    geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
        @Override
        public void onKeyEntered(String key, GeoLocation location) {


            Log.e("id", key);
            Location to = new Location("to");
            to.setLatitude(location.latitude);
            to.setLongitude(location.longitude);
            if (!fetchedUserIds) {
                userIdsToLocations.put(key, to);

            } else {
                userIdsToLocations.put(key, to);
                addUserListener(key);
            }


        }

        @Override
        public void onKeyExited(String key) {
            Log.d("TAG", "onKeyExited: ");
            if (userIdsWithListeners.contains(key)) {
                int position = getUserPosition(key);
                arrayList.remove(position);
                adapter.notifyItemRemoved(position);
            }
        }

        @Override
        public void onKeyMoved(String key, GeoLocation location) {

        }

        @Override
        public void onGeoQueryReady() {

            initialListSize = userIdsToLocations.size();
            if (initialListSize == 0) {
                fetchedUserIds = true;
            }
            iterationCount = 0;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                userIdsToLocations.keySet().forEach(this::addUserListener);
            }
        }

        private void addUserListener(String key) {
            databaseReference = FirebaseDatabase.getInstance().getReference().child("buses").child(key);
            databaseReference.addValueEventListener(userValueListener);
            userIdsWithListeners.add(key);
        }


        @Override
        public void onGeoQueryError(DatabaseError error) {

        }
    });


    geoQueries.add(geoQuery);
}
 private void setuplist() {
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    adapter = new Adapter(this, arrayList);
    recyclerView.setAdapter(adapter);
}


private void setupFirebase() {
    databaseReference = FirebaseDatabase.getInstance().getReference().child(("tracker"));
    fire = new GeoFire(databaseReference);
    getrecyclerview();
}


private void getrecyclerview() {

    userValueListener = new ValueEventListener() {

        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

            Mylist mylist = dataSnapshot.getValue(Mylist.class);

            mylist.setTextView(dataSnapshot.child("text").getValue().toString());

            if (arrayList.contains(mylist)) {

                update(mylist);
            } else {

                newdata(mylist);
            }


        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    };

}
 private void newdata(Mylist mylist) { // for new data inserted

    iterationCount++;
    arrayList.add(0, mylist);

    if (!fetchedUserIds && iterationCount == initialListSize) {
        fetchedUserIds = true;
        adapter.setUsers(arrayList);
    } else if (fetchedUserIds) {
        adapter.notifyItemInserted(getIndexOfNewUser(mylist));
    }
}
   private void update(Mylist mylist) {
    int position = getUserPosition(mylist.getTextView());
    arrayList.set(position, mylist);
    adapter.notifyItemChanged(position);
}

private int getUserPosition(String id) {
    for (int i = 0; i < arrayList.size(); i++) {
        if (arrayList.get(i).getTextView().equals(id)) {
            Log.d("LOG_TAG", "getIndexOfNewUser: " + i);
            return i;
        }
    }
    return -1;
}

private int getIndexOfNewUser(Mylist u) {

    for (int i = 0; i < arrayList.size(); i++) {
        if (arrayList.get(i).getTextView().equals(u.getTextView())) {
            Log.d("index", "getIndexOfNewUser: " + i);
            return i;
        }
    }
    throw new RuntimeException();
}

private void removeListeners() {
    for (GeoQuery geoQuery : geoQueries) {
        geoQuery.removeAllListeners();
    }

    for (String userId : userIdsWithListeners) {
        databaseReference =
                          FirebaseDatabase.getInstance().getReference().child("buses").child(userId);
        databaseReference.removeEventListener(userValueListener);
    }
}

My Adpter code

public class Adapter extends RecyclerView.Adapter<Adapter.Myholder> {

ArrayList<Mylist> arrayList;
Context context;

public Adapter(Context context, ArrayList<Mylist> arrayList)
{
    this.context=context;
    this.arrayList=arrayList;
}

@NonNull
@Override
public Myholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    LayoutInflater layoutInflater=LayoutInflater.from(parent.getContext());
    View view=layoutInflater.inflate(R.layout.samplecard,parent,false);


    return new Myholder(view);
}

@Override
public void onBindViewHolder(@NonNull Myholder holder, int position) {

    final Mylist mylist=arrayList.get(position);

    holder.textView.setText(mylist.getTextView());

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {


            Intent intent=new Intent(context,MapsActivity.class);
            intent.putExtra("id",mylist.getTextView());
            context.startActivity(intent);
        }
    });

}

@Override
public int getItemCount() {
    return arrayList.size();
}

public void setUsers(List<Mylist> list) {
    arrayList = (ArrayList<Mylist>) list;
    notifyDataSetChanged();
}

public class Myholder extends RecyclerView.ViewHolder {
    TextView textView;
    public Myholder(@NonNull View itemView) {
        super(itemView);
        textView=itemView.findViewById(R.id.mytext);
    }

}

public Mylist getUser(int position) {
    if (position > arrayList.size() - 1) {
        return new Mylist();
    } else {
        return arrayList.get(position);
    }
}}

whenever the onKeyExited is called i want to remove that data from recyclerview but the application crashed when i reopen the application its runs successfully.

  2020-06-11 14:46:21.752 16559-16559/com.pranay.test2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.pranay.test2, PID: 16559
java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1
    at java.util.ArrayList.remove(ArrayList.java:506)
    at com.pranay.test2.MainActivity$4.onKeyExited(MainActivity.java:208)
    at com.firebase.geofire.EventListenerBridge.onDataExited(EventListenerBridge.java:52)
    at com.firebase.geofire.GeoQuery$4.run(GeoQuery.java:162)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:232)
    at android.app.ActivityThread.main(ActivityThread.java:7172)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:576)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:888)

Upvotes: 0

Views: 198

Answers (1)

Alex Rmcf
Alex Rmcf

Reputation: 924

Method getUserPosition(String id) can return -1, but it is impossible for array to have -1 position. So you suppose to check here:

 public void onKeyExited(String key) {
            Log.d("TAG", "onKeyExited: ");
            if (userIdsWithListeners.contains(key)) {
                int position = getUserPosition(key);
                if (position!=-1){
                arrayList.remove(position);
                adapter.notifyItemRemoved(position);
                }
            }
        }

Upvotes: 1

Related Questions