I have phone contact numbers list stored in an array and called contactsString[]
and in an online database registered users numbers
I want to count how many registered users are there
and there is my code
for (i=0;i<contactsString.length-1;i++){
Phone phone=new Phone();
phone.phone=contactsString[i]
WebService.getInstance().getApi().checkNumber(phone).enqueue(new Callback<MainResponse>() {
#Override
public void onResponse(Call<MainResponse> call, Response<MainResponse> response) {
if (response.body().status==1){
availableUsers++;
}
}
#Override
public void onFailure(Call<MainResponse> call, Throwable t) {
}
});
}
my problem is the web service response is delayed so it don't count and availableUsers is printed it's initial value which is 0
I would try better sending an array of Phone objects. In this way you would get the correct answer in 1 call.
I would never do this in the way you implemented: imagine you have 500 contacts: you will be doing 500 calls to your server. Now imagine you have 100000 users with 500 contacts each
Try to customize your api call in this format. Which uses async task class.
private void phoneContact() {
new AsyncTask<String,Void,String>() {
#Override
protected String doInBackground(String ... params) {
try {
Platform http = Url_Contacts;
JSONObject resp = http.search(what,where);
Log.d(TAG, "Response: " + resp.toString());
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return "";
}
}.execute();
}
Make sure that your service works well and the format of json with value status in there.
In onResponse, run on UIThread to update your View with the availableUsers.
The enqueue method is asynchronous. So your code should respect the multithreaded nature of it.
There are many approaches you can take:
Replace enqueue() method with execute(). But that makes all the calls synchronous. If you call it in UI Thread then whole app can stutter. Probably you will get NetworkOnMainThreadException. Not a good approach anyway.
Use RxAndroid or RxJava with Observer pattern.
Simple solution. Create a variable int callsFinished = 0;. In onResponse increment that variable. Then if that callsFinished == contactsString.length that means all calls have been done.
In your activity add a listener
void onAllCallsFinished(int availableUsers) {
//do what you want with availableUsers information
}
Call onAllCallsFinished(availableUsers) when callsFinished == contactsString.length.
There you can do what you want with that data. Update a view, call another service.
Related
I have a Java (Android) code that has callback, now I want to extract that code to its separate function for reusability, here is what I have:
InternQuery query = InternQuery.builder().build();
ApolloCall<InternQuery.Data> apolloCall = new HoraApolloClient(this.context).getHoraApolloClient().query(query);
apolloCall.enqueue(new ApolloCall.Callback<InternQuery.Data>() {
#Override
public void onResponse(#Nonnull Response<InternQuery.Data> response) {
InternQuery.Data rData = response.data();
// some error handling code ...
InternQuery.Intern intern = rData.intern();
}
#Override
public void onFailure(#Nonnull ApolloException e) { }
});
Here you can see I am using Android Apollo client for GraphQL. So I have a function .enqueue which has a callback, in callback onResponse I can get my intern object.
Now I want to take this code into seperate method in a InternApi class, so code will loke something like that:
public InternsQuery.Intern getIntern() {
// the code above goes here ...
}
The problem here is that How can I return from that function my intern object, as .enqueue is asynchronous, and my getIntern function will return earlier, I need to make it wait my callback.
Generally I guess, I need something like async/await. So I expect my code to be something like that:
public InternsQuery.Intern getIntern() {
InternsQuery.Intern intern = await apolloCall.enqueue();
return intern;
}
Is there async/await in java, or any other way of solving it?
Ideally I want it in a functional way, so my getIntern method returns intern. I believe I could pass reference to intern object that I create earlier and assign it in my callback, but it seems to be a bad solution.
I am trying to build a Rest client with Retrofit 2. This is the first time using this library.
Most of the examples that I have seen normally use a callback function in Android activity or view.
http://www.vogella.com/tutorials/Retrofit/article.html
https://github.com/MeetMe/TwitchTvClient/tree/master/src/com/wdonahue/twitchtvclient
I was wondering if, in the code below, one could return an object of type Appver instead of void?
Thank you!
public void GetAppver()
{
Call<Appver> call = endPoint.GetAppver();
call.enqueue(new Callback<Appver>()
{
#Override
public void onResponse(Call<Appver> call, Response<Appver> response)
{
if (response.isSuccessful())
{
Appver appver = response.body();
}
}
#Override
public void onFailure(Call<Appver> call, Throwable t) { }
});
}
I guess you want to have Appver because you need to use this object to possibly poulate the UI for instance inside a RecyclerView, in this case I guess you cannot avoid to not use void, because you are extending the library. But for sure you can use Dagger2 or a Singleton although there are some contraindications to maintain an instance of Appver so that you can use it in an Adapter for instance
Also in real life is rarely used Retrofit2 in this way, usually you implement it with RXJava2 or with Google Architecture components as ViewModel,LiveData and LifeCycle
You can call Retrofit service methods synchronously.
public AppVer GetAppVer() {
Call<AppVer> call = endPoint.GetAppver();
Response<AppVer> response;
try {
response = call.execute();
} catch (IOException e) {
// Handle network communication errors here
}
if (!response.isSuccessful()) {
// Handle REST service errors here
}
return response.body();
}
However, as you know, you can't do network communication on the main thread in Android. You have to wrap the call in e.g. a Thread, AsyncTask or Service.
Have a look at the following links how to structure your app.
Android Architecture Blueprints: https://github.com/googlesamples/android-architecture
Android Architecture Components: https://developer.android.com/topic/libraries/architecture
I am making an Android application and have decided to use Azure's DB platform. I find adding entries to different tables very easy, but querying the DB to be almost impossible.
Currently I am trying to follow this model: How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?
In short, it uses an interface to implement a AsyncTask with my query executing in doInBackground(). My problem with this is that it is many many lines of code to execute a single simple query, AND I will need to be doing multiple unique queries when running my app and creating tens of separate interfaces/classes seems extremely inefficient.
At the end of the day all I want is to get the results from this query in a managable way:
final MobileServiceList<Users> result = mUser.where().field("username").eq(username).execute().get();
However it seems to not execute without being wrapped in a AsyncTask like this:
new AsyncTask<Users, Void, Users>() {
#Override
protected Users doInBackground(Users... params) {
try {
final MobileServiceList<Users> result = mUser.where().field("username").eq(username).execute().get();
if(result.size() > 0) {
System.out.println("something in list");
return result.get(0);
}
} catch (Exception exception) {
exception.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Users result) {
System.out.println("in post");
if(username.equals((result.username)) && password.equals(result.password)) {
System.out.println("found user");
}
}
}.execute();
Is there any easy way to get around this? All I want is a result from a simple query, I don't understand how this is so hard..
Thanks!
Unfortunately, there is not any simple way to get around this, please refer to AsyncTask reference to know it for helping Android UI thread to get result asynchronously.
So, I am a newbie Android programmer trying to learn RxJava/RxAndroid.
The App I am developing to study has a local database (using Cupboard) that is backed by an API. It has two screens: one showing a list of items and other the items details. Whenever I need to show the items I call this method to load them from my local database and:
public void getItems() {
List<Item> Items = cupboard().withDatabase(database).query(Item.class).list();
if (Items == null || Items.isEmpty()) {
service.listItems().enqueue(new Callback<Items>() {
#Override
public void onResponse(Call<Items> call, Response<Items> response) {
if (response.isSuccessful()) {
cupboard().withDatabase(database).put(response.body().getItems());
mDataReceiver.onItemsLoaded(response.body().getItems());
} else {
Log.d(ItemsLoader.class.getSimpleName(), response.message());
}
}
#Override
public void onFailure(Call<Items> call, Throwable t) {
Log.d(ItemsLoader.class.getSimpleName(), t.getMessage());
}
});
} else {
mDataReceiver.onItemsLoaded(Items);
}
}
If nothing (empty list or null) is returned, I load them from the API, save it in my local database and returns it to the user.
I was trying to refactor this code into reactive (using RxJava, RxAndroid and RxCupboard) by chaining my database calls with the API call, when need, using flatMap but I just couldn't make it work nor wrap my head around it.
Is it possible to refactor this code into Reactive or should I leave this way? If possible, what would be the right way to do this?
This can be solved with a PublishSubject. You can publish data (and errors!) on this object when onResponse() or onFailure() is called. PublishSubject is also an Observable so you can subscribe to its data.
See docs.
I was recently reading about design patterns and especially about low coupling and delegation.
I was wondering, whether there should be any logic on the Activity class or if it only serves the view.
E.g. I have an activity called BattleActivity and that is supposed to work as some kind of session between two players. A lot of Push Notifications happen there, also the class works as an Observer, so there is a lot of comminication going on there.
Right now I am trying to figure out what logic could I move to a separated object(and whether I should) and then just work with the activity.
Example of one of my methods on the activity:
private void postCastedSpell(final int spellId) {
Call call = StaticGlobalContainer.api.postSpellToBattle(Integer.parseInt(battleId), Integer.parseInt(MainActivity.CURRENT_USER_ID), spellId, 100);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Response<User> response, Retrofit retrofit) {
User user = response.body();
if (response.code() == 202) {
// 200
Log.i("Posting spell to battle", "Success");
Boolean affectedUserIsOpponent = isUserOpponent(user);
if (affectedUserIsOpponent && user.currentHp<1){
StaticGlobalContainer.battleOnResult(Constants.WON, getApplicationContext());
}else {
updateBattleLog(affectedUserIsOpponent, user, spellId);
}
// TODO: do something here
} else {
// 404 or the response cannot be converted to User.
Log.e("Posting spell to battle", "Error:" + response.errorBody());
}
}
#Override
public void onFailure(Throwable t) {
Log.i("HttpRequest-Post spell", "Failure");
}
});
}
It's not specifically bad to put a lot of logic in Activities, but you're right to try to keep it only view related things. If the app is relatively small, it might not be worth moving the logic out. Also, there is some overhead to using abstractions.
if your abstractions aren't supplying a significant benefit, you should avoid them
I try to keep any big data objects in a manager class, so given your example, it might worthwhile to create a Battle manager class to hold all the logic involved in it, like this postCastedSpell function. This way all the Battle information is self contained, and also can be used elsewhere in other activities.
Just keep in mind if you're use data manager classes and you want them to prompt some sort of interation with the UI, you'll have to use Callbacks or the Bus pattern since the Battle manager won't have access to your UI. For example, to call the postCastedSpell the call would look like:
BattleActivity:
BattleManager bm = BattleManager.getInstance(user1, user2);
onSpellClicked() {
bm.castSpell(spellId, user1, callback)
}
BasicCallback callback = new BasicCallback() {
#Override
onComplete() {
if (MyInfoFragment.this.isVisible()) {
[Update UI]
}
}
};
NOTE: When using callbacks like my example, when it finally gets called the activity may have already gone out of view and have been already garbage collected. So in the callback function you need to first make sure it is still visible before trying to modify the UI that possibly no longer exists.