0

I am trying a project with Rx, dagger,realm,retrofit in MVP pattern.I am not expert in this libraries and i do not know a lot about these libs.

In project in Scope Application i declare realm config and then get instance it for inject to my presenter.

In the first Activity called LoginActivityو As it finds it name, this activity use for login to app. I have two edittext for inserting username and pasword and i have a button for login.when the button is clicked in ViewLogin i have made an observable of clicks:

public Observable<Object> observeLoginBtn() {
    return RxView.clicks(mBinding.buttonLogin);
} 

and in LoginPresenter i have implemented this observable for login task by RX. When username and password was correct, service will return a User information as a json to client.

{
"User": {
    "Address": "     ",
    "BirthDate": "1395/09/28",
    "Email": " ",
    "EnableExpireDate": null,
    "FirstName": "kia",
    "JobLocations": {
        "AllowDomains": "9,13",
        "Altitude": "12",
    },
    "UserImage": [..]...
}

This is a part of json.By Actually by gson i have returned needed information to client. Now I want to store this information in device by realm.I have done login task by rx and when server returns user information i got this information in onNext:

        .switchMap(new Function<Response<String>, ObservableSource<UserInfo>>() {
            @Override
            public ObservableSource<UserInfo> apply(Response<String> stringResponse) throws Exception {
                String orginCookie = stringResponse.raw().header("Set-Cookie")
                        + "domain=" +
                        stringResponse.raw().header("Access-Control-Allow-Origin");
                String cookie = SerializeUtil.serializeCookie(orginCookie);
                return model.getLoginUser(info[0], cookie);
            }
        })
        .observeOn(AndroidSchedulers.mainThread())
   .subscribeWith(new DisposableObserver<UserInfo> (){
       @Override
       public void onNext(UserInfo userInfo) {

As you now onNext executes on the Ui thread. Now in this section i want to store this information by realm: First of all, i have to create a RealmObject according by user response:

public class UserInfo{
@SerializedName("User")
    private User user;
    public static UserInfo objectFromData(String str) {
        return new Gson().fromJson(str, UserInfo.class);
    }
    public User getUser() {
        return user;
    }
    public void setUser(User User) {
        this.user = User;
    }
}

Nested User class:

public class User extends RealmObject implements RealmModel {
    public User objectFromData(String str) {

        return new Gson().fromJson(str, User.class);
    }
    @SerializedName("Tel")
    private String Tel;
    @SerializedName("UserName")
    private String UserName;
    @SerializedName("UserImage")
    private RealmList<Integer> UserImage;
   @SerializedName("JobLocations")
   private JobLocations jobLocations;
    .... //getter and setter
}

Nested JobLocations class:

public class JobLocations extends RealmObject implements RealmModel {
    public static JobLocations objectFromData(String str) {
        return new Gson().fromJson(str, JobLocations.class);
    }
    @SerializedName("AllowDomains")
    private String AllowDomains;
    @SerializedName("Altitude")
    private String Altitude;
    @SerializedName("City")
    private String City;
    .... // getter and setter
}

I have created repository for insert my model to db:

public class DatabaseRealm implements IDatabaseRealm{
...
@Override
public <T extends RealmObject> T add(T model) {
    realm.beginTransaction();
    realm.copyToRealm(model);
    realm.commitTransaction();
    return model;
}

This is where ,the write is happened. This is where that i have made observable for insert my model to db:

public class TaskRepositoryImpl implements Repository<User> {
...
@Override
public Observable<User> add(final User model) {
    return Observable.create(new ObservableOnSubscribe<User>() {
        @Override
        public void subscribe(ObservableEmitter<User> emitter) throws Exception {
            try {
                databaseRealm.add(model);
                emitter.onNext(model);
                emitter.onComplete();
            }catch (Exception e) {
                emitter.onError(e);
            }
        }
    });
}

In loginPresenter in subscribeWith method that i have received my json user info i am usin realm like this:

.subscribeWith(new DisposableObserver<UserInfo> (){
               @Override
               public void onNext(UserInfo userInfo) {
                    taskRepository.add(userInfo.getUser())
                            .subscribeOn(Schedulers.trampoline())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(new DisposableObserver<User>() {
                                @Override
                                public void onNext(User user) {

                                }

                                @Override
                                public void onError(Throwable e) {

                                }

                                @Override
                                public void onComplete() {

                                }
                            });

Now i have two main queastion: 1- Is the good place for storing data.I mean in onNext at subscribeWith?

2- There is a user image in response from server and it my has a large size.I think storing in realm accrue in ui thread it can make ANR error.How can i store this information on background thread in my pattern?

Excuse me that my text was long I tried to explain it perfectly and clearly.

Cyrus the Great
  • 5,145
  • 5
  • 68
  • 149
  • Please don't explain everything concise your problem with that problem code – Zulqurnain Jutt Apr 01 '18 at 06:30
  • I want to guys understand that what i have done!!! For a better help.sorry – Cyrus the Great Apr 01 '18 at 06:38
  • **first question :** yes or maybe , entirely depends on why you want to store it and for what use , **second question:** you can convert image to bitmap bytes then store it using rxjava , but i recommend you store the path to image and store the image locally in sdcard or somewhere – Zulqurnain Jutt Apr 01 '18 at 06:47
  • Ok dude ,but in second question, the image that received from server is a byte array.I send data immediately after receiving to realm for storing. for converting byteArray to file and storing the path's file to db I have to done in `DatabaseRealm` class and add method.But converting must be execute on background thread.how could i execute add method in `DatabaseRealm` class on background?it was my main question – Cyrus the Great Apr 01 '18 at 07:02
  • I don't see any file creation or bytes generating code in above given snippet , post that and i'll take a look what is missing – Zulqurnain Jutt Apr 01 '18 at 07:18
  • I do not have created any file yet. because my question was doing transactions on background thread .According realm official web page we can do `Asynchronous transaction` by `executeTransactionAsync` method. Now that i have used of Rx how can i do that? – Cyrus the Great Apr 01 '18 at 07:22

1 Answers1

1

1.) I'm surprised private String UserName; is not a @PrimaryKey

2.)

@Override
public <T extends RealmObject> T add(T model) {
    realm.beginTransaction();
    realm.copyToRealm(model);
    realm.commitTransaction();
    return model;
}

Could be

@Override
public <T extends RealmModel> Single<T> add(T model) {
    return Single.create((emitter) ->
        if(model.isManaged()) {
            return model;
        } 
        realm.executeTransactionAsync((r) -> {
             r.insertOrUpdate(model); // if has primary key 
        }, () -> {
            emitter.onSuccess(model);
        }, (throwable) -> {
            emitter.onError(throwable);
        } 
    );
}

Or something very similar. Then you can flatMap the Single to handle the success route.

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • dude this is my changes :http://codepad.org/PlexnZWH as your suggestion.But how could i handle `emitter.onSuccess` or `emitter.onError(error);` from rx in my presenter: http://codepad.org/5wYL2Pht – Cyrus the Great Apr 02 '18 at 07:06
  • I have impelimented my presenter like this: http://codepad.org/RmeIkzio is it true? – Cyrus the Great Apr 02 '18 at 07:18
  • Uh. I'll just go with "I hope you don't have Realm illegal thread access and try it out" – EpicPandaForce Apr 02 '18 at 11:50
  • Thanks dude. i am confused so much.in this post i describe how create instance from realm: https://stackoverflow.com/questions/49609966/realm-access-from-incorrect-thread-in-rx-and-dagger . – Cyrus the Great Apr 02 '18 at 11:54