Armin Orlik Armin Orlik - 1 year ago 124
Java Question

Android Realm Arraylist and simple POJO

guys i retrieve from outside database (using retrofit) many (6600 rows) of object which looks and works with my POJO class. After that i try to put it into Realm object but its very slow. I suspect that this slow action is because i begin i commit transaction row by row. Maybe anybody know how to put full arraylist to realm object in one commit?
My Main:

private class AsyncTaskRetro extends AsyncTask<Void, Void, Void> {

@Override
protected Void doInBackground(Void... voids) {

PlacesAPI.Factory.getInstance().getPlaces().enqueue(new Callback<Places>() {

@Override
public void onResponse(Call<Places> call, Response<Places> response) {
for (int i = 0; i < response.body().getPosts().size(); i++) {
RowModel rowModel = new RowModel(response.body().getPosts().get(i).getNazwa(),
Double.parseDouble(response.body().getPosts().get(i).getSzer()),
Double.parseDouble(response.body().getPosts().get(i).getDlug()));
rowModels.add(rowModel);
}
String oldName;
oldName = rowModels.get(0).getName();
shopsNames.add(rowModels.get(0).getName());


mRealm.beginTransaction();
RowModel rowModelRealm = mRealm.createObject(RowModel.class);
mRealm.commitTransaction();
for (int j = 0; j < rowModels.size(); j++) {
mRealm.beginTransaction();
rowModelRealm.setName(rowModels.get(j).getName());
rowModelRealm.setLattitude(rowModels.get(j).getLattitude());
rowModelRealm.setLongitude(rowModels.get(j).getLongitude());
mRealm.commitTransaction();

if (rowModels.get(j).getName().equals(oldName)) {
continue;
}
oldName = rowModels.get(j).getName();
shopsNames.add(rowModels.get(j).getName());
}



//sortowanie

listy z nazwami sklepow
Collections.sort(shopsNames);

adapter = new ShopsAdapter(MainActivity.this, shopsNames);

recyclerView.setAdapter(adapter);


}

@Override
public void onFailure(Call<Places> call, Throwable t) {

}
});

return null;
}
}


and POJO:

public class RowModel extends RealmObject {

@Required
private String name;
@Required
private Double lattitude, longitude;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Double getLattitude() {
return lattitude;
}

public void setLattitude(Double lattitude) {
this.lattitude = lattitude;
}

public Double getLongitude() {
return longitude;
}

public void setLongitude(Double longitude) {
this.longitude = longitude;
}

public RowModel(String name, Double lattitude, Double longitude) {
this.name = name;
this.lattitude = lattitude;
this.longitude = longitude;
}

public RowModel() {
}
}

Answer Source

1.) you're using Realm 0.82.2, and that version has quirks which is why the next stable version I recommend is 0.87.5; but in reality the latest stable version (at the moment) is 3.1.4.

You should probably switch to a version that isn't 2 years old?

2.) You are running an AsyncTask, but you use enqueue in it:

getPlaces().enqueue(new Callback<Places>() {    
      @Override
      public void onResponse(Call<Places> call, Response<Places> response) {

This means that Retrofit callback will execute on UI thread.

Then, you do synchronous transactions, so you're writing to Realm on the UI thread, which is bad.

3.) you're trying to manually sort the downloaded elements and then showing them in the adapter also manually, which doesn't make sense if you're using Realm, because Realm allows sorting elements by a particular field. Also shopsNames is definitely not a RealmResults, meaning you aren't even listening for changes made to the DB.

ShopsAdapter should be a RealmBaseAdapter.


So the code should be more like this

private class AsyncTaskRetro
        extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... voids) {
        try(Realm r = Realm.getDefaultInstance()) {
            Response<Place> response = PlacesAPI.Factory.getInstance().getPlaces().execute();
            Place place = response.body();
            List<Post> posts = place.getPosts();
            r.executeTransaction((realm) -> {
                for(Post post : posts) {
                    RowModel rowModel = new RowModel(post.getNazwa(),
                            Double.parseDouble(post.getSzer()),
                            Double.parseDouble(post.getDlug()));
                    rowModels.add(rowModel);
                }
                String oldName;
                oldName = rowModels.get(0).getName();
                shopsNames.add(rowModels.get(0).getName());

                RowModel rowModelRealm = realm.createObject(RowModel.class);
                for(RowModel rowModel : rowModels) {
                    rowModelRealm.setName(rowModel.getName());
                    rowModelRealm.setLattitude(rowModel.getLattitude());
                    rowModelRealm.setLongitude(rowModel.getLongitude());

                    if(rowModel.getName().equals(oldName)) {
                        continue;
                    }
                    oldName = rowModel.getName();
                    shopsNames.add(rowModel.getName());
                }
            });
            // no need to manually sort if you use RealmBaseAdapter with findAllSorted()
        }
        return null;
    }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download