0

I'm getting multi objects from an API call and I'm trying to display the them into a ListView.

Code is as follows

public class ExerciseActivity extends AppCompatActivity {

private CompositeDisposable disposables = new CompositeDisposable();
private ExerciseClient exerciseClient;
private List<Exercise> exerciseList;

private Realm realm;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_exercise);
    exerciseList = new ArrayList<>();

    this.realm = Realm.getDefaultInstance();
    exerciseClient = new ExerciseClient(this);
    populateExerciseList();

}

private void setupExerciseList() {
    ListView lvItems = findViewById(R.id.lvItems);
    ArrayAdapter<Exercise> adapter = new ArrayAdapter<>(this, R.layout.list_view, exerciseList);
    lvItems.setAdapter(adapter);
}


void populateExerciseList() {
    disposables.add(exerciseClient.getExercises()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                    this::getExercisesSuccess,
                    this::getExercisesError
            )
    );
}

private void getExercisesError(Throwable throwable) {
    exerciseList = realm.where(Exercise.class).findAll();
    setupExerciseList();

}

private void getExercisesSuccess(List<Exercise> exercises) {
    this.realm.executeTransaction(realm -> realm.where(Exercise.class).findAll().deleteAllFromRealm());
    for (int i = 0; i < exercises.size(); i++) {
        Exercise foundExercise = exercises.get(i);
        this.exerciseList.add(foundExercise);
        this.realm.executeTransactionAsync(realm -> realm.copyToRealmOrUpdate(foundExercise));

    }
    setupExerciseList();
}

The list would only load between 0 and 3-4 elements, if I comment the this.realm.executeTransactionAsync(realm -> realm.copyToRealmOrUpdate(foundExercise)); line, the list loads as expected.

Keep in mind I have 1000 objects I have to gather from the API.

My guess is that the this.realm.executeTransactionAsync(realm -> realm.copyToRealmOrUpdate(foundExercise)); takes too long to compute thus by the time the app starts I only get < 5 entries.

Is there any possible workarounds?

Edit: Also, I've deleted some entries from the database to only ~50 and it seems to work now even with that line present, so the problem is definitely the big chunk of data.

Andrei
  • 77
  • 1
  • 6
  • Rx and ListView? What a strange combination :D anyways, use `RealmBaseAdapter` from https://github.com/realm/realm-android-adapters – EpicPandaForce Jan 31 '18 at 12:39

1 Answers1

0

How about

public class ExerciseActivity extends AppCompatActivity {

    private CompositeDisposable disposables = new CompositeDisposable();
    private ExerciseClient exerciseClient;

    private Realm realm;
    private RealmResults<Exercise> results;
    private RealmBaseAdapter<Exercise> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_exercise);
        exerciseList = new ArrayList<>();

        this.realm = Realm.getDefaultInstance();
        this.results = realm.where(Exercise.class).findAllAsync();
        this.adapter = new RealmBaseAdapter<Exercise>(results);
        exerciseClient = new ExerciseClient(this);
        populateExerciseList();

        ListView lvItems = findViewById(R.id.lvItems);
        lvItems.setAdapter(adapter);
    }

    void populateExerciseList() {
        disposables.add(exerciseClient.getExercises()
                .subscribeOn(Schedulers.io())
                .subscribe(
                        this::getExercisesSuccess,
                        this::getExercisesError
                )
        );
    }

    private void getExercisesError(Throwable throwable) {
        runOnUiThread(() -> {
            // d'oh
        });
    }

    private void getExercisesSuccess(List<Exercise> exercises) {
        try(Realm r = Realm.getDefaultInstance()) {
            r.executeTransaction(realm -> {                     
               realm.where(Exercise.class).findAll()
                       .deleteAllFromRealm();
                for(Exercise exercise: exercises) {
                    realm.insertOrUpdate(exercise);
                }
            });
        }
    }
}
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • Hi, thank you for your help. So I've tried your suggestion and used [this](https://codeshare.io/5vXXBD) code but it won't populate my list view at all. Is there anything I'm missing? – Andrei Feb 01 '18 at 09:38
  • Also, in the `getExercisesSuccess` , it successfully detects all the entries, not sure where the problem is – Andrei Feb 01 '18 at 09:55
  • `insertOrUpdate()` should be inside `executeTransaction` block – EpicPandaForce Feb 01 '18 at 10:19
  • Thanks man, works as expected now. Am I right to believe that the cached data will be loaded straight from the `onCreate` method (if server is unreachable) and `getExercisesError` has nothing to do with this regard? – Andrei Feb 01 '18 at 10:34
  • It will automatically load data from Realm, and update it with new entries, yes. If you run into anything strange with the animation (because you delete all items + re-add all items), then look at this trick I have for merging data https://stackoverflow.com/a/39352718/2413303 (it's in the EDIT) – EpicPandaForce Feb 01 '18 at 10:36