2015-08-31 25 views
6

Tôi bắt đầu sử dụng RxJava kết hợp với SqlBrite và tôi đang gặp một số sự cố với toán tử zip.RxJava và Sqlbrite - toán tử nào sử dụng

Giả sử tôi có 2 lớp, UserTweet.

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

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

Và bảng của họ tương ứng SQLite:

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

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

và tương ứng SqlBrite DAO họ

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

Như bạn có thể thấy trong UserDao, tôi đã cố gắng sử dụng kết hợp các toán tử zipflatMap để điền danh sách Tweet cho mỗi User.

Câu hỏi đầu tiên: có cách nào tốt hơn để làm điều đó không?

Thứ hai câu hỏi: đó zip điều hành dường như để treo mãi mãi và không bao giờ hoàn thành ... Tôi thấy rằng tweetDao.getTweetsByUser(user) được gọi nhưng Func của zip không bao giờ được gọi là ... có ai có một ý tưởng tại sao?

Câu hỏi thứ ba: có cách nào tốt hơn để chuyển đổi Observable<List<T>> thành số Observable<T> ngoài việc sử dụng kết hợp flatMapfrom?

Chết tiệt, RxJava mạnh mẽ nhưng đường cong học tập khá dốc ...

Trả lời

4

Tại sao không để cơ sở dữ liệu xử lý kết nối?

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

Bạn có thể phải đổi tên một số cột nếu hai bảng có cột có cùng tên.

Tìm hiểu thêm về tham gia here

+0

Tôi đoán điều đó cũng có thể hoạt động. Tôi sẽ phải nhóm từng hàng tweet mỗi người dùng –

+0

@LordRaydenMk, làm thế nào về nếu nó là một sql phức tạp và ông đã sử dụng phương thức wrapContentProvider? –

Các vấn đề liên quan