I am building an android library.
The main class includes methods like connect,getUserSession .Workflow includes few steps-
Step 1 :
In getUserSession method. I need to send a Http POST request to external api and
recieve the response data(sessionKey,id,name etc). It is like an authentication method.
Step 2 :
In connect method. It uses the response data from Step 1 then I need to connect to websocket server recieve the response data(userdetails,profilepic etc).
Step3 :
Pass the response data from Step 2 in Activity.
I want to be step 1 and step 2 to be synchrounous because step 2 won't work without step 1. And i dont want to block the app while processing.After doing some research i found this can be done using AsyncTask class. But it seems i cannot return values from doInBackground and onPostExecute methods. How to do this task?
You have to set listener (interface) for first AsyncTask Please try below code
interface AsyncTaskListener{
public void onTaskCompleted(Object<Type> value);
}
public class DemoAsyncTask extends AsyncTask<String,Void,Void>{
AsyncTaskListener listener;
public DemoAsyncTask(AsyncTaskListener listener){
this.listener = listener;
}
#Override
protected String doInBackground(Void... params) {
///do some task
return someResult;
}
#Override
protected void onPostExecute(String result) {
listener.onTaskCompleted(result);
}
//Calling Async task from activity or fragment
DemoAsyncTask task = new DemoAsyncTask(new AsyncTaskListener(){
#Override
public void on onTaskCompleted(Object<Type> value);{
//do your second step here
})
};
task .execute();
Related
I am new in programming and in Android development. I have 3 asynchronous method to get data from server in my MainActivity, let say it is called
getUserDataFromServer()
getProductsDataFromServer()
getBannersFromServer()
if every request takes 1 second, then it needs 3 seconds to complete those 3 request If I chain it one after the other (in series).
so what I want is.... I want to make those 3 request asynchronously (in parallel) then if those 3 request has been done (either failed or success) then I want to do something else, let say to show up the Toast message. so I can finish it faster, maybe it just need around 1,2 s, not 3 s.
I don't know how to do it or what the special method called to wrap it in Android ?
how to do that in Java or Kotlin ?
The following code should help you get started for your purposes. It also has explanations of what is happening. You can change the parameters as required:
Executing the Task:
MyTask myTask = new MyTask();
myTask.execute(String1);
//OR:
new MyTask().execute(String1, String2, String3...);
Creating the Task:
//The first type in AsyncTask<> is for specifying the type of input given.
//Second parameter: Type of data to give to onProgressUpdate.
//Third parameter: Type of data to give to onPostExecute.
private class MyTask extends AsyncTask<String, String, String> {
private String resp;
ProgressDialog progressDialog;
#Override
protected String doInBackground(String... params) {
publishProgress("Processing ..."); // Calls onProgressUpdate()
//params is the input you've given that can be used for processing.
getUserDataFromServer()
getProductsDataFromServer()
getBannersFromServer()
//Result is the String to give onPostExecute when the task is done executing.
String result = "Done Processing";
return result;
}
#Override
protected void onPostExecute(String result) {
// Get the result from your task after it is done running.
progressDialog.dismiss();
//IMPORTANT: As you asked in your question, you can now execute whatever code you
//want since the task is done running.
}
#Override
protected void onProgressUpdate(String... text) {
//Progress has been updated. You can update the proggressDialog.
}
}
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.
I am a iOS programmer (not very experienced). I usually create a HttpClient.class for all other class to use. Like:
#implementation HttpClient
-(NSString*)getGetResponse :(NSString*)url{
//do all http get request work
return result;
}
#end
Then I can call this getGetResponse: anywhere in my project to do the http get work.
NSString *result = [httpClient getGetResponse:#"http://www.example.com/api"]
But Android request network running in class extends AsyncTask.Like:
public class HttpTask extends AsyncTask<String,String, String > {
#Override
protected String doInBackground(String... params) {
//network code here
return result;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
This makes me confused. How do I do the same thing like the objective-c code does above?(return the result back to caller)
You don't. HTTP calls need to happen asycnhronously. Instead of returning a result, forcing the thread to wait, you need to do any processing that requires the result in onPostExecute.
I have a problem with proper use AsyncTask. I use AsyncTask to communicate with the server. I run server connection in AsyncTask doInBackground. My app listens in the background and as soon as captured message uses publishProgress. Then I can use message in my App. In my application I am doing login to the server and if it was successful new activity will start. I need to communicate with the server also in the new activity but the connection was created in the background AsyncTask. I don't know how I can communicate through established connection in new activity. Can anyone give me advice? Thank you a lot!
Please take a look on code. I have this code in LoginUser class and after succesful login to the server new Activity starts.
//init
private ConnectionClass mConnectClass;
private connectTask mTask;
//execute connectTask
mTask = new connectTask();
mTask.execute("");
public class connectTask extends AsyncTask<String, String, ConnectionClass> {
#Override
protected ConnectionClass doInBackground(String... message) {
Log.i("Terminal", "doInBackground.");
mConnectClass = new ConnectionClass(
new ConnectionClass.OnMessageReceived() {
#Override
// here the messageReceived method is implemented
public void messageReceived(String message) {
// this method calls the onProgressUpdate
publishProgress(message);
}
});
Log.i("Terminal", "Starting...");
mConnectClass.connectServer();
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
answerFromServer = Arrays.toString(values);
// serverMessage.append("S: " + Arrays.toString(values) + "\n");
}
}
Don't use AsyncTask for this. You seem to want to hold your connection open for an extended period of time. AsyncTask is only supposed to be used for tasks that last at most a few seconds. You might consider using a Service instead.
my goal is to insert to a certain db 2 values, id and pass.
I have a registeration page which asks for that data and a button to complete the action.
So on the button listener what should I do?many told me to use AsyncTask (which I don't know to use) instead of Thread.
Remember that this class needs to get 2 parameters id and pass .. and as far as I know threads starts after using the start() method which invoke the run method, and the run method has no parameters.. so how can I pass those 2 parameters?
Anyway I'm very confused.
Another thing is that if I get any kind of error on the catch block I will put the error on a certain string something like : String error = exceptionInstance.toString(); and then I can take see that string from the registeration page and print the error.
myThreadInstance.start();
textViewInstance.setText(myThreadInstance.getError());
It's some kind of a marathon.. I'M CONFUSED!!!!!!!
According to me use AsyncTask instead of an Thread because it's easy to use and you have better control on Background thread without doing extra code for creating separate logic for updating Ui when Thread execution complete, calculate progress units to so user how much time take by an operation to done etc
Your First question how you send username and password to AsyncTask on button click .for this use AsyncTask Constructor as:
LoginOperation loginopertion=new LoginOperation(strusername, strpassword);
loginopertion.execute("");
Your Second answer how we receive username and password in AsyncTask and update Ui when Task complete for this use onPostExecute of AsyncTask to update Ui when doInBackground execution complete for example :
public class LoginOperation extends AsyncTask<String, Void, String> {
String strusername,strpassword;
public LoginOperation(String strusername, String strpassword){
this.strusername=strusername;
this.strpassword=strpassword;
}
#Override
protected void onPreExecute() {
//show progressbar here
}
#Override
protected String doInBackground(String... params) {
string result="";
try
{
result=="success or fail";
//do your network opertion here
}
catch(SQLException e)
{
result="ERROR";
}
return result;
}
#Override
protected void onPostExecute(String resultmsg) {
// show error here and update UI
//or other opertion if login success
textViewInstance.setText(resultmsg);
}
}
For more information about AsyncTask method's see
http://developer.android.com/reference/android/os/AsyncTask.html