@NonNull
  @Override
  public Person mapFromCursor(@NonNull Cursor cursor) {
    final StorIOSQLite storIOSQLite = storIOSQLiteFromPerformGet.get();

    // BTW, you don't need a transaction here
    // StorIO will wrap mapFromCursor() into the transaction if needed

    final long personId = cursor.getLong(cursor.getColumnIndexOrThrow(PersonsTable.COLUMN_ID));
    final String personUuid =
        cursor.getString(cursor.getColumnIndexOrThrow(PersonsTable.COLUMN_UUID));
    final String personName =
        cursor.getString(cursor.getColumnIndexOrThrow(PersonsTable.COLUMN_NAME));

    final List<Car> personCars =
        storIOSQLite
            .get()
            .listOfObjects(Car.class)
            .withQuery(
                Query.builder()
                    .table(CarsTable.TABLE_NAME)
                    //                            .where(CarsTable.COLUMN_PERSON_ID + "=?")
                    //                            .whereArgs(personId)
                    .where(CarsTable.COLUMN_PERSON_UUID + "=?")
                    .whereArgs(personUuid)
                    .build())
            .prepare()
            .executeAsBlocking();

    return new Person.Builder(personName).uuid(personUuid).cars(personCars).build();
  }
  void reloadData() {
    uiStateController.setUiStateLoading();

    final Subscription subscription =
        storIOSQLite
            .get()
            .listOfObjects(Tweet.class)
            .withQuery(TweetsTable.QUERY_ALL)
            .prepare()
            .createObservable() // it will be subscribed to changes in tweets table!
            .delay(
                1,
                SECONDS) // for better User Experience :) Actually, StorIO is so fast that we need
                         // to delay emissions (it's a joke, or not)
            .observeOn(mainThread())
            .subscribe(
                new Action1<List<Tweet>>() {
                  @Override
                  public void call(List<Tweet> tweets) {
                    // Remember: subscriber will automatically receive updates
                    // Of tables from Query (tweets table in our case)
                    // This makes your code really Reactive and nice!

                    // We guarantee, that list of objects will never be null (also we use
                    // @NonNull/@Nullable)
                    // So you just need to check if it's empty or not
                    if (tweets.isEmpty()) {
                      uiStateController.setUiStateEmpty();
                      tweetsAdapter.setTweets(null);
                    } else {
                      uiStateController.setUiStateContent();
                      tweetsAdapter.setTweets(tweets);
                    }
                  }
                },
                new Action1<Throwable>() {
                  @Override
                  public void call(Throwable throwable) {
                    // In cases when you are not sure that query will be successful
                    // You can prevent crash of the application via error handler
                    Timber.e(throwable, "reloadData()");
                    uiStateController.setUiStateError();
                    tweetsAdapter.setTweets(null);
                  }
                });

    // Preventing memory leak (other Observables: Put, Delete emit result once so memory leak won't
    // live long)
    // Because rx.Observable from Get Operation is endless (it watches for changes of tables from
    // query)
    // You can easily create memory leak (in this case you'll leak the Fragment and all it's fields)
    // So please, PLEASE manage your subscriptions
    // We suggest same mechanism via storing all subscriptions that you want to unsubscribe
    // In something like CompositeSubscription and unsubscribe them in appropriate moment of
    // component lifecycle
    unsubscribeOnStop(subscription);
  }
Beispiel #3
0
  private GetObjectStub(boolean withTypeMapping) {
    this.withTypeMapping = withTypeMapping;

    storIOSQLite = mock(StorIOSQLite.class);
    internal = mock(StorIOSQLite.Internal.class);

    when(storIOSQLite.internal()).thenReturn(internal);

    query = Query.builder().table("test_table").build();

    rawQuery =
        RawQuery.builder().query("select * from who_cares").observesTables("test_table").build();

    //noinspection unchecked
    getResolver = mock(GetResolver.class);
    cursor = mock(Cursor.class);

    item = new TestItem();

    when(cursor.getCount()).thenReturn(1);

    when(cursor.moveToNext())
        .thenAnswer(
            new Answer<Boolean>() {
              int invocationsCount = 0;

              @Override
              public Boolean answer(InvocationOnMock invocation) throws Throwable {
                return invocationsCount++ < 1;
              }
            });

    when(storIOSQLite.get()).thenReturn(new PreparedGet.Builder(storIOSQLite));

    when(storIOSQLite.observeChangesInTables(eq(singleton(query.table()))))
        .thenReturn(Observable.<Changes>empty());

    assertThat(rawQuery.observesTables()).isNotNull();

    when(storIOSQLite.observeChangesInTables(rawQuery.observesTables()))
        .thenReturn(Observable.<Changes>empty());

    when(getResolver.performGet(storIOSQLite, query)).thenReturn(cursor);

    when(getResolver.performGet(storIOSQLite, rawQuery)).thenReturn(cursor);

    when(getResolver.mapFromCursor(cursor)).thenReturn(item);

    //noinspection unchecked
    typeMapping = mock(SQLiteTypeMapping.class);

    if (withTypeMapping) {
      when(internal.typeMapping(TestItem.class)).thenReturn(typeMapping);
      when(typeMapping.getResolver()).thenReturn(getResolver);
    }
  }