I'm using Syncano latest Android SDK (4.0.6).
Is there a way to have a async query with parameters?
Syncano.please(User.class).where()
Doesn't have a method to run it asynchronously.
But
Syncano.getInstance().getObjects(User.class)
Which has 'sendAsync()' but doesn't have 'where()' constrain.
Docs specifies:
Syncano.please(User.class).getAsync(callback);
But I don't see it in code only getAll().
You can make an async call when using please(). Just pass SyncanoCallback object.
Syncano.please(Item.class).get(new SyncanoListCallback<Item>() {
#Override
public void success(ResponseGetList<Item> response, List<Item> result) {
}
#Override
public void failure(ResponseGetList<Item> response) {
}
});
You're right that async get() method is missing when using where(). It has to be fixed in the library, but you can make this call anyway saving the reference to RequestBuilder.
RequestBuilder<Item> please = Syncano.please(Item.class);
please.where().eq(Item.COLUMN_NUMBER, 11);
please.get(new SyncanoListCallback<Item>() {
#Override
public void success(ResponseGetList<Item> response, List<Item> result) {
}
#Override
public void failure(ResponseGetList<Item> response) {
}
});
You can also use where(), without using please(). It will look like this:
Where<Item> where = new Where<>();
where.eq(Item.COLUMN_NUMBER, 11);
Syncano.getInstance().getObjects(Item.class).setWhereFilter(where).sendAsync(new SyncanoListCallback<Item>() {
#Override
public void success(ResponseGetList<Item> response, List<Item> result) {
}
#Override
public void failure(ResponseGetList<Item> response) {
}
});
Related
I have one case when I need to return an observable immediately, but then replace this observable with another one.
Here is an example
private Flowable<byte[]> mFlowableStream = Flowable.empty();
#Override
public Flowable<byte[]> startStreamRead() {
bindToService();
return mFlowableStream;
}
And then after binding to service I provide it a callback connection like that
#Override
public void bindToService() {
mAppContext.bindService(new Intent(mAppContext,StreamService.class), mServiceConnection, 0);
}
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
mServiceInterection = ((StreamServiceInterection.LocalBinder) binder).getServiceInteractor();
mStreamDisposable = mServiceInterection.getStream()
.subscribe(new Consumer<byte[]>() {
#Override
public void accept(byte[] data) throws Exception {
}
});
}
What I want to do is to somehow replace returned previously mFlowableStream with a new observable that I got from service.
What are possible strategies to implement this ? Maybe I should return some other value, like Future.
Please suggest how to solve this problem
Thanks
You can use Flowable.create instead of Flowable.empty
Then when new data come, just push to flowable.
Like Example
final ArrayList<FlowableEmitter<Integer>> arrEmitter = new ArrayList<>();
Flowable<Integer> futureFlow = Flowable.create(new FlowableOnSubscribe<Integer>() {
#Override
public void subscribe(final FlowableEmitter<Integer> e) throws Exception {
e.onNext(1);
e.onNext(2);
arrEmitter.add(e); // hold emitter to use later
}
}, BackpressureStrategy.BUFFER);
futureFlow.subscribe(new ResourceSubscriber<Integer>() {
#Override
public void onNext(Integer integer) {
System.out.println("onNext: " + integer);
}
#Override
public void onError(Throwable t) {
}
#Override
public void onComplete() {
System.out.println("onComplete");
}
});
// =========== When data come
FlowableEmitter<Integer> holdEmitter = arrEmitter.get(0);
holdEmitter.onNext(3);
Or use you can use **Subject* type according to your need
Understanding RxJava Subject — Publish, Replay, Behavior and Async Subject
I use the following class to make an API call in android using Retrofit
public Class Checkin {
public static void checkinViaApi(CheckinSendModel checkinSendModel) {
final ApiHandler apiHandler = new ApiHandler();
apiHandler.setApiResponseListener(new ApiResponseListener() {
#Override
public void onApiResponse(ApiResponseModel apiResponse) {
Log.i("CheckedIn","true");
}
#Override
public void onApiException(Error error) {
Log.i("fail",error.getErrorMessage());
}
});
List<CheckinSendModel> checkinSendModelList = new ArrayList<CheckinSendModel>();
checkinSendModelList.add(checkinSendModel);
Call<ApiResponseModel> request = RetrofitRestClient.getInstance().checkinToMainEvent(checkinSendModelList,Constant.API_KEY);
apiHandler.getData(request);
}
}
I call that method as follows:
Checkin.checkinViaApi(checkinSendModelObject);
Now, when the API call is successful, I want to execute a function checkedInSuccessfully() in the class from where I make the call. How can I do it?
Thanks in advance
Pass in the response interface.
public class Checkin {
public static void checkinViaApi(CheckinSendModel checkinSendModel, ApiResponseListener listener) {
final ApiHandler apiHandler = new ApiHandler();
apiHandler.setApiResponseListener(listener);
Other class - Call that method
CheckinSendModel model;
Checkin.checkinViaApi(model, new ApiResponseListener() {
#Override
public void onApiResponse(ApiResponseModel apiResponse) {
Log.i("CheckedIn","true");
checkedInSuccessfully();
}
#Override
public void onApiException(Error error) {
Log.i("fail",error.getErrorMessage());
}
);
Interface is your handy man. Create an interface like below.
Interface CheckInListener {
void onCheckIn();
}
Change the checkinViaApi() to below signature.
public static void checkinViaApi(CheckinSendModel checkinSendModel, CheckinListener listener) {
#Override
public void onApiResponse(ApiResponseModel apiResponse) {
Log.i("CheckedIn","true");
listener.onCheckIn();
}
}
When you call the above function you can provide an instance of the interface.
Checkin.checkinViaApi(checkinSendModelObject, new CheckInListener() {
#Override
void onCheckIn() {
//Do your action here
}
});
I'm trying to use the Quickblox Android SDK combined with RxJava to make some chained and time-based Quickblox API calls. The API already have async methods. Here are two of them:
Create a session:
QBAuth.createSession(new QBEntityCallbackImpl<QBSession>() {
#Override
public void onSuccess(QBSession session, Bundle params) {
}
#Override
public void onError(List<String> errors) {
}
});
Create a Dialog (Chat Room)
QBChatService.getInstance().getGroupChatManager().createDialog(qbDialog,
new QBEntityCallbackImpl<QBDialog>() {
#Override
public void onSuccess(QBDialog dialog, Bundle args) {
}
#Override
public void onError(List<String> errors) {
}
});
As you saw, every API call must have a Callback Implementation as method parameter. The problem is that I have to make some chained API calls. Example:
Create empty session, then
Sign in, then
Retrieve user info, then
Login to chat service, then
....
I searched a little bit about RxJava and I saw that it's good to solve this kind of problem, because you can apply some filters and other things before make the next API call. The problem is that I don't know how to adapt this API to work with RxJava.
Should the API call with callbacks be inside the Observable call() method?
Should the onError() and the onSuccess() methods of the Quickblox API call the onError() and the onNext()/onCompleted() methods of the Subscriber?
Could anyone make some example of the use of
RxJava to create a session and then create a dialog using the
provided create session and create dialog API methods?
Here's a example of how to create observables using Observable.create() in your case:
Observable<QBSession> connectionObservable = Observable.create(new OnSubscribe<QBSession>() {
#Override
public void call(Subscriber<? super QBSession> subscriber) {
if (!subscriber.isUnsubscribed()) {
QBAuth.createSession(new QBEntityCallbackImpl<QBSession>() {
#Override
public void onSuccess(QBSession session, Bundle params) {
subscriber.onNext(session);
subscriber.onCompleted();
}
#Override
public void onError(List<String> errors) {
subscriber.onError(/*some throwable here*/);
}
});
}
}
});
Observable<QBDialog> dialogCreationObservable = Observable.create(new OnSubscribe<QBDialog>() {
#Override
public void call(Subscriber<? super QBDialog> subscriber) {
if (!subscriber.isUnsubscribed()) {
QBChatService.getInstance().getGroupChatManager().createDialog(qbDialog,
new QBEntityCallbackImpl<QBDialog>() {
#Override
public void onSuccess(QBDialog dialog, Bundle args) {
subscriber.onNext(dialog);
subscriber.onCompleted();
}
#Override
public void onError(List<String> errors) {
subscriber.onError(/*some throwable here*/);
}
});
}
}
});
So I'll try to keep this question as to-the-point as possible, but it will involve code snippets that traverse an entire codepath.
For context, I am fairly new and completely self-taught for Android dev, so please notify me of any clear misunderstandings/poor organization throughout. The main focus of the question is bug I am experiencing now, which is that, after a network request, the variable that was supposed to be set as a result of that network request is null, because the code moved forward before the network request completed.
Here is my activity method. It is supposed to populate the mFriends variable with the result of mUserPresenter.getUserList(), which is (unfortunately) null:
/**
* Grabs a list of friends, populates list with UserAdapter
*/
#Override
public void onResume(){
super.onResume();
mUserPresenter = new UserPresenter();
mFriends = mUserPresenter.getUserList();
if (mGridView.getAdapter() == null) {
UserAdapter adapter = new UserAdapter(getActivity(), mFriends);
mGridView.setAdapter(adapter);
}
else{
((UserAdapter)mGridView.getAdapter()).refill(mFriends);
}
}
Here is how I am structuring my UserPresenter method getUserList:
public List<User> getUserList()
{
ApiService.get_friends(this);
return mUserList;
}
The real magic happens in the ApiService class:
public static void get_friends(final UserPresenter userPresenter){
ApiEndpointInterface apiService = prepareService();
apiService.get_friends().
observeOn(AndroidSchedulers.mainThread())
.subscribe(
new Action1<List<User>>()
{
#Override
public void call(List<User> users) {
userPresenter.setList(users);
}
}
);
}
My thinking was, that by calling userPresenter.setList(users) in ApiService, that would set mUserList to the response from the api request. However, instead, mUserList == null at the time that getUserList responds.
Any ideas of how I can structure this?
I have also started to learn something similar. Here, I would rather use callbacks.
In your presenter,
public void setList(List<User> users) {
yourView.setUserList(users);
}
And your activity which implements a view (MVP)
#Override
public void setUserList(List<User> users) {
((UserAdapter)mGridView.getAdapter()).refill(mFriends);
}
Also, check that retrofit is not returning null list.
I have a made a small app when I was learning about all this. It fetches user data from GitHub and shows in a list. I was also working with ORMLite and Picasso so some db stuff is there. Dagger Dependency is also used (but you can ignore that). Here's the link.
Here's how my Presenter behaves:
private DataRetrieverImpl dataRetriever;
#Override
public void getUserList(String name) {
dataRetriever.getUserList(name);
}
#Override
public void onEvent(DataRetrieverEvent event) {
UserList userList = (UserList)event.getData();
mainView.setItems(userList);
}
DataRetrieverImpl works as a module (sort of).
private DataRetriever dataRetriever;
restAdapter = new RestAdapter.Builder().setEndpoint(SERVER_END_POINT).build();
dataRetriever = restAdapter.create(DataRetriever.class);
public void getUserList(final String name) {
Log.i(TAG, "getting user list for: " + name);
Observable<UserList> observable = dataRetriever.getUserList(name);
Log.i(TAG, "subscribe to get userlist");
observable.subscribe(new Action1<UserList>() {
#Override
public void call(UserList userList) {
eventBus.post(new DataRetrieverEvent("UserList", userList));
// save to database
for (User user : userList.getItems()) {
Log.i(TAG, user.getLogin());
try {
dbHelper.create(user);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}, new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
});
}
And DataRetriever is interface for retrofit. I'm sorry for the naming confusion.
public interface DataRetriever {
#GET("/search/users")
public Observable<UserList> getUserList(#Query("q") String name);
}
Any my Activity,
#Override
public void setItems(final UserList userList) {
runOnUiThread(new Runnable() {
#Override
public void run() {
UserAdapter userAdapter = (UserAdapter)recyclerView.getAdapter();
userAdapter.setUserList(userList);
userAdapter.notifyItemRangeInserted(0, userAdapter.getItemCount());
}
});
}
I want to display a new activity on success callback of my WebService called by Retrofit.
And I have difficulties to find examples on how to use Retrofit callback result to launch new activity.
Is that a good way to do it ? Do I have to clean up some stuff before?
public void validate(View view) {
RetrofitWebServices.getInstance().webserviceMethod(params,new Callback<MyObject>() {
#Override
public void success(MyObject object, Response response) {
Intent barIntent = new Intent(FooActivity.this, BarActivity.class);
startActivity(barIntent);
}
#Override
public void failure(RetrofitError error) {
...
}
});
}
You can implement Callback with weak reference to Context
public class MyCallback implements Callback<MyObject> {
WeakReference<Context> mContextReference;
public MyCallback(Context context) {
mContextReference = new WeakReference<Context>(context);
}
#Override
public void success(MyObject arg0, Response arg1) {
Context context = mContextReference.get();
if(context != null){
Intent barIntent = new Intent(FooActivity.this, BarActivity.class);
context.startActivity(barIntent);
} else {
// TODO process context lost
}
}
#Override
public void failure(RetrofitError arg0) {
// TODO process error
}
}
Just remember - this solution will not work if Context lost occurred while request in progress but you may don't worry about potential memory leak which may be if you keep strong reference to Context object.
Hi have a solution that seems easier: use the getApplicationContext() function.
I am not 100% sure it is OK, but in my case it works as expected.
Your code would be:
public void validate(View view) {
RetrofitWebServices.getInstance().webserviceMethod(params,new Callback<MyObject>() {
#Override
public void success(MyObject object, Response response) {
Intent barIntent = new Intent(getApplicationContext(), BarActivity.class);
startActivity(barIntent);
}
#Override
public void failure(RetrofitError error) {
...
}
});
}