2015-08-31 53 views
6

我開始使用RxJava並結合SqlBrite,我對zip運算符有一些問題。RxJava和Sqlbrite - 要使用哪個運算符

比方說,我有2個類,UserTweet

public class User { 
    public long id; 
    public List<Tweet> users; 
    ... 
} 

public class Tweet { 
    public long id; 
    public User poster; 
    ... 
} 

及其各自的SQLite表:

user 
--------- 
id INTEGER PRIMARY KEY 

tweet 
--------- 
id INTEGER PRIMARY KEY 
poster_id INTEGER 
FOREIGN KEY(poster_id) REFERENCES user(id) 

及彼等各自之SqlBrite DAO

userDAO的:

public class UserDao { 
    private final BriteDatabase briteDb; 
    private final TweetDAO tweetDao; 

    ... 

    public Observable<List<User>> getUsersWithTheirTweets() { 
     Observable<User> usersObs = briteDb.createQuery("user", "SELECT * FROM user") 
       .map(new Func1<SqlBrite.Query, List<User>>() { 
        @Override 
        public List<User> call(SqlBrite.Query query) { 
         Cursor cursor = query.run(); 
         List<User> result = new ArrayList<>(cursor.getCount()); 
         while (cursor.moveToNext()) { 
          User user = UserTable.parseCursor(cursor); 
          result.add(user); 
         } 
         cursor.close(); 
         return result; 
        } 
       }) 
       // transform Observable<List<User>> into Observable<User> 
       .flatMap(new Func1<List<User>, Observable<User>>() { 
        @Override 
        public Observable<User> call(List<User> users) { 
         return Observable.from(users); 
        } 
       }); 

     // combine each user with his tweets 
     return Observable.zip(usersObs, usersObs.flatMap(new Func1<User, Observable<List<Tweet>>>() { 
      @Override 
      public Observable<List<Tweet>> call(User user) { 
       return tweetDao.getTweetsByUser(user); 
      } 
     }), new Func2<User, List<Tweet>, User>() { 
      @Override 
      public User call(User user, List<Tweet> tweets) { 
       user.tweets = tweets; 
       return user; 
      } 
     }).toList(); 
    } 

} 

TweetDAO:

public class TweetDAO { 
    private final BriteDatabase briteDb; 

    ... 

    public Observable<List<Tweet>> getTweetsForUser(final User user) { 
     briteDb.createQuery("tweet", "SELECT * FROM tweet WHERE poster_id = ?", Long.toString(user.id)) 
       .map(new Func1<SqlBrite.Query, List<User>>() { 
        @Override 
        public List<Tweet> call(SqlBrite.Query query) { 
         Cursor cursor = query.run(); 
         List<Tweet> result = new ArrayList<>(cursor.getCount()); 
         while (cursor.moveToNext()) { 
          Tweet tweet = TweetTable.parseCursor(cursor); 
          tweet.user = user; 
          result.add(tweet); 
         } 
         cursor.close(); 
         return result; 
        } 
       }) 
    } 
} 

正如您在UserDao中看到的那樣,我嘗試使用zipflatMap運算符的組合來爲每個User填充Tweet的列表。

第一個問題:有沒有更好的方法來做到這一點?

第二個問題:那zip運營商似乎永遠掛永不結束......我看到tweetDao.getTweetsByUser(user)被稱爲但是zipFunc永遠不會被調用......有沒有人有一個想法,爲什麼?

第三個問題:除了使用flatMapfrom的組合之外,是否有更好的方法將Observable<List<T>>轉換爲Observable<T>

媽的,這是RxJava強大,但學習曲線相當陡峭...

回答

4

爲什麼不讓數據庫處理加入?

SELECT * FROM user INNER JOIN tweet ON user._id = tweet.poster_id 

如果兩個表具有相同名稱的列,則可能必須重命名某些列。

更多關於加入here

+0

我想這也可以。我將不得不爲每個用戶分組每個推文行 –

+0

@LordRaydenMk,如果它是一個複雜的SQL,並且他使用wrapContentProvider方法? –