AngryMan Studios AngryMan Studios - 23 days ago 5
Android Question

ArrayList not updating after using .clear()

I'm new to Android development, so please bear with me.

I have a custom ArrayAdapter which I want to update by swiping down to refresh.

I understand that in order to do this I need to:


  • clear the ArrayList that holds my data (with .clear())

  • Update the ArrayList with the new data (using the getAbsentTeachers() method)

  • use notifyDataSetChanged() on the ArrayAdapter



After I clear the ArrayList, call getAbsentTeachers() and notifyDataSetChanged() the ArrayList appears to remain empty even though getAbsentTeachers() is beeing called. I know this because nothing is displayed in my ListView.

getAbsentTeachers() populates the ArrayList fine when my app is first launched however it doesn't seem to work when I call it again to update the ArrayList.

Any ideas as to why the array is not beeing updated?

MainActivity.java:
package uk.co.bobsmith.drawview.drawviewtest;

public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {

private ArrayList<Absent> absences = new ArrayList<>();
private SwipeRefreshLayout swipeContainer;

@Override
protected void onCreate(Bundle savedInstanceState) {

//---------------------INITIALISING PARSE-------------------------------
Parse.enableLocalDatastore(this);

// Add your initialization code here
Parse.initialize(new Parse.Configuration.Builder(getApplicationContext())
//Information obscured for privacy - tested and working though.
.applicationId("")
.clientKey(null)
.server("")
.build()
);

ParseUser.enableAutomaticUser();
ParseACL defaultACL = new ParseACL();
// Optionally enable public read access.
// defaultACL.setPublicReadAccess(true);
ParseACL.setDefaultACL(defaultACL, true);

ParseInstallation.getCurrentInstallation().saveInBackground();
ParsePush.subscribeInBackground("Absent");

//-----------------------CREATE ADAPTER OBJECT--------------------------------

getAbsentTeachers();

final ListView lv = (ListView)findViewById(R.id.listView);
final ArrayAdapter<Absent> adapter = new absenceArrayAdapter(this, 0, absences);
lv.setAdapter(adapter);

swipeContainer = (SwipeRefreshLayout) findViewById(R.id.swipeContainer);
// Setup refresh listener which triggers new data loading
swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
// Code to refresh the list.
absences.clear();
getAbsentTeachers();
adapter.notifyDataSetChanged();
swipeContainer.setRefreshing(false);
// Call swipeContainer.setRefreshing(false) when finished.
}
});

}

// Populates absences ArrayList with absence data
public void getAbsentTeachers() {

ParseQuery<ParseObject> query = ParseQuery.getQuery("Absences");

query.findInBackground(new FindCallback<ParseObject>() {
@Override
public void done(List<ParseObject> objects, ParseException e) {
if(e == null){

for(ParseObject object : objects){

String name = String.valueOf(object.get("name"));
Log.i("Name", name);
String desc = String.valueOf(object.get("description"));
Log.i("Description", desc);

absences.add(new Absent(name, desc, "employees"));

}

} else {

Log.i("Get data from parse", "There was an error getting data!");
e.printStackTrace();

}
}
});

}



//custom ArrayAdapter
class absenceArrayAdapter extends ArrayAdapter<Absent> {

private Context context;
private List<Absent> absencesList;

public absenceArrayAdapter(Context context, int resource, ArrayList<Absent> objects) {
super(context, resource, objects);

this.context = context;
this.absencesList = objects;
}

public View getView(int position, View convertView, ViewGroup parent) {
//get the property we are displaying
Absent teacher = absencesList.get(position);

//get the inflater and inflate the XML layout for each item
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.custom_listview, null);

TextView name = (TextView) view.findViewById(R.id.name);
TextView description = (TextView) view.findViewById(R.id.description);
ImageView teacherImage = (ImageView) view.findViewById(R.id.imageView);

String teacherName = teacher.getTeacherName();
name.setText(teacherName);

int descriptionLength = teacher.getDescription().length();
if(descriptionLength >= 75){
String descriptionTrim = teacher.getDescription().substring(0, 75) + "...";
description.setText(descriptionTrim);
}else{
description.setText(teacher.getDescription());
}

return view;

}

}
}

Answer

Move these two lines to after the if-else within the done of the Parse call.

adapter.notifyDataSetChanged();
swipeContainer.setRefreshing(false);

You currently are not waiting for the Parse call to finish before notifying the adapter.


Another solution is to change

absences.add(new Absent(name, desc, "employees"));

to

adapter.add(new Absent(name, desc, "employees"));