Search code examples
javaandroidarraylistrealm

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() {
    }
}

Solution

  • 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;
        }
    }