How to get refference on object on reccursion? - android

I am starting asynctask from activity. Sometimes SearchAdd does not returns desired result ( due to TimeOuts etc) So, i call it recursivly up to 5 times. But I messed up, how to update refenece to SearchAdd in activity after selfcall.
SearchAdd s = new SearchAdd(callback);
s.execute();
Asyntask
public class SearchAdd extends AsyncTask<Void, Void, JSONObject> {
private SearchAddInterface callback;
private int trial = 0;
public SearchAdd(SearchAddInterface callback) {
this.callback = callback;
}
public SearchAdd(SearchAddInterface callback, int trial) {
this.callback = callback;
this.trial = trial;
}
#Override
protected JSONObject doInBackground(Void... arg0) {
return JSONParser.getJSONfromURL(RequestStringCreater
.concatenationStrings().replaceAll("\\s", "%20"));
}
#Override
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
if (result == null){
if(trial <5){
SearchAdd sAdd = new SearchAdd(callback, trial);}
}
}else{
// do job
}
}

To remove the recursion and allow the request to be cancelled, you can do this:
public class SearchAdd extends AsyncTask<Void, Void, JSONObject> {
private SearchAddInterface callback;
private int trial = 0;
private boolean cancel = false;
public SearchAdd(SearchAddInterface callback) {
this.callback = callback;
}
public void cancel() {
cancel = true;
}
#Override
protected JSONObject doInBackground(Void... arg0) {
JSONObject result = null;
while (!cancel && (trial < 5) && (result == null)) {
trial++;
result = JSONParser.getJSONfromURL(RequestStringCreater.concatenationStrings().replaceAll("\\s", "%20"));
}
return result;
}
#Override
protected void onPostExecute(JSONObject result) {
super.onPostExecute(result);
if (cancel) {
// The request was cancelled
} else if (result == null) {
// All trials have failed.
} else {
// Do job
}
}
}

Related

AsyncTask, how to properly use WeakReference in all the UI methods

I want to use the WeakReference approach to not leak memory with my AsyncTask. I found examples online and on Stackoverflow, but they only get the reference in onPostExecute and I am unsure how to correctly use it in all 3 of the UI methods.
My current approach is like this, but I have no clue if I can get rid of some redundancy. Why can't I just call activityReference.get() in the constructor and then only check for null in each of the UI methods? Why do the examples online call get right before using the WeakReference?
private static class ExampleAsyncTask extends AsyncTask<Integer, Integer, String> {
private WeakReference<MainActivity> activityReference;
ExampleAsyncTask(MainActivity context) {
activityReference = new WeakReference<>(context);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) {
return;
}
activity.progressBar.setVisibility(View.VISIBLE);
}
#Override
protected String doInBackground(Integer... integers) {
for (int i = 1; i < integers[0]; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress((i * 100) / integers[0]);
}
return "Finished";
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) {
return;
}
activity.progressBar.setProgress(values[0]);
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
MainActivity activity = activityReference.get();
if (activity == null || activity.isFinishing()) {
return;
}
activity.progressBar.setProgress(0);
activity.progressBar.setVisibility(View.INVISIBLE);
Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();
}
}
You can initialise it in the constructor and use it in all methods.
private static class ExampleAsyncTask extends AsyncTask<Integer, Integer, String>
{
private WeakReference<MainActivity> activityReference;
MainActivity activity;
ExampleAsyncTask(MainActivity context)
{
activityReference = new WeakReference<>(context);
activity = activityReference.get();
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
if (activity == null || activity.isFinishing())
{
return;
}
activity.progressBar.setVisibility(View.VISIBLE);
}
#Override
protected String doInBackground(Integer... integers)
{
if (activity == null)
return null;
for (int i = 1; i < integers[0]; i++)
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
publishProgress((i * 100) / integers[0]);
}
return "Finished";
}
#Override
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
if (activity == null || activity.isFinishing())
{
return;
}
activity.progressBar.setProgress(values[0]);
}
#Override
protected void onPostExecute(String s)
{
super.onPostExecute(s);
if (activity == null || activity.isFinishing())
{
return;
}
activity.progressBar.setProgress(0);
activity.progressBar.setVisibility(View.INVISIBLE);
Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();
}
}
The most correct and obvious way to use weak reference here is not to. Instead, you should cancel the task when Activity gets destroyed. This will prevent memory leak and stop async computation which became useless.
public final class SomeActivity extends Activity {
private AsyncTask<?, ?, ?> runningTask;
private void startTaskPlease() {
if (runningTask != null) runningTask.cancel(true);
runningTask = new ExampleAsyncTask(this);
runningTask.execute();
}
#Override protected void onDestroy() {
super.onDestroy();
if (runningTask != null) runningTask.cancel(true);
}
}
Now your AsyncTask#doInBackground should be interruption-friendly, but UI part should not mind weak references and cancellation.
public final class ExampleAsyncTask extends AsyncTask<whatever> {
private final SomeActivity activity; // now this is OK! Thanks to cancellation
public ExampleAsyncTask(SomeActivity activity) {
this.activity = activity;
}
}

get value from asynctask

I found many subject about but I can't get a solution, I'm doing a soap request in doInBackground method of asyncTask, and I want to get an Integer to know if the process is done, here I call my asyncTask:
Simulation.AsyncSoapCall task = new Simulation.AsyncSoapCall();
try {
Integer taskResult = task.execute().get();
} catch (Exception e) {
e.printStackTrace();
}
My AsyncTask class:
private class AsyncSoapCall extends AsyncTask<Void, Void, Integer> {
Integer result;
Boolean isInternetPresent = false;
Boolean isUrlAvailable = false;
ConnectionDetector cd;
AsyncSoapCall(){
}
#Override
protected Integer doInBackground(Void... params) {
cd = new ConnectionDetector(getActivity().getApplicationContext());
// get Internet status
isInternetPresent = cd.isConnectingToInternet();
// check for Internet status
if (isInternetPresent) {
String namespace = getResources().getString(R.string.NAMESPACE);
String url = getResources().getString(R.string.URL);
String soapaction = getResources().getString(R.string.SOAP_ACTION);
String login = getResources().getString(R.string.login);
String mdp = getResources().getString(R.string.mdp);
isUrlAvailable = cd.isUrlAvailable();
// check for Internet status
if (isUrlAvailable) {
String idApplication = Installation.id(getActivity());
SOAPContact soapContact = new SOAPContact(namespace, url, soapaction, login, mdp);
soapContact.saveParams(getResources().getString(R.string.origine), db);
result = 1;
} else {
result = 2;
}
} else {
result = 3;
}
return result;
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute");
}
#Override
protected void onProgressUpdate(Void... values) {
Log.i(TAG, "onProgressUpdate");
}
}
I don't get error my app crasha at this line:
Integer taskResult = task.execute().get();
try to get the value from onPostExecute like
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
int yourNum = result;
}
that's it
Did you read the doc?
https://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask has no "get" method.
You need to define a OnPostExecute method which will be called when your task is over with your Integer as a parameter.
public class MyActivity extends Activity
{
private Integer myInteger;
private void blabla(){
Simulation.AsyncSoapCall task = new Simulation.AsyncSoapCall() {
#Override
protected void onPostExecute(Integer result) {
//... Your code here ...
MyActivity.this.myInteger = result;
MyActivity.this.myMethod(result);
}
}
try {
task.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
protected void myMethod(Integer integer){
}
}
Here is one method with the help of interfaces,
MainActivity.java
public class MainActivity extends AppCompatActivity {
static String TAG=MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AsyncSoapCall request = new AsyncSoapCall(new AsyncSoapCall.AsyncSoapInterface() {
#Override
public void callBack(String callBackValue) {
Log.d(TAG,callBackValue);
}
});
request.execute();
}
}
AsyncSoapCall.java
public class AsyncSoapCall extends AsyncTask<Void,Void,Void> {
interface AsyncSoapInterface{
void callBack(String callBackValue);
}
AsyncSoapInterface callbackObj;
AsyncSoapCall(AsyncSoapInterface callbackObj)
{
callbackObj = callbackObj;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
callbackObj.callBack("Your value");
}
}

Android Asyntask, second parameter is sending information before of first

I need to get the information of the Async methods using SOAP request, from "layer_1" before receiving the information from "layer_2", but sometimes it happens the other way round, is there any way to make "layer_2" wait for the end of "layer_1"?
Its my AsyncTask:
protected Void doInBackground(String... params) {
String ope = params[0];
switch (ope)
{
case "layer_1":
if(Util.isNetworkAvailable(mContext.getApplicationContext()))
{
getWebservice = WebService.getLayer(COD_MATRICULA);
changeAsync = true;
}
break;
case "layer_2":
if (Util.isNetworkAvailable(mContext.getApplicationContext())) {
if(canMade)
message = addUserWeb(User);
changeAsync = true;
callMessage = true;
}
else
{
message = null;
changeAsync = false;
}
break;
}
publishProgress();
return null;
}
and in my progressupdate:
protected void onProgressUpdate(Void... values) {
if (changeAsync)
verifyUser();
if(callMessage)
{
.......
callMessage = false;
}
}
You can used two asyncTask in your project like below
//layer_1
private class AsyncTaskRunner1 extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(String... params) {
if(Util.isNetworkAvailable(mContext.getApplicationContext()))
{
getWebservice = WebService.getLayer(COD_MATRICULA);
changeAsync = true;
}
}
#Override
protected void onPostExecute(String result) {
AsyncTaskRunner2 myTask = new AsyncTaskRunner2();
myTask.execute();
}
}
//layer_2
private class AsyncTaskRunner2 extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(String... params) {
if (Util.isNetworkAvailable(mContext.getApplicationContext())) {
if(canMade)
message = addUserWeb(User);
changeAsync = true;
callMessage = true;
}
}
#Override
protected void onPostExecute(String result) {
}
}

Android AsyncTask json return value

I have called an async task from my button click.In the doInBackground I have called an API and It is returning me a Json object.I want to pass the Json object to another activity on the button click.How can I can get the return Json object value so that I can send it to other activity.
Thanks.
Create Interface
public interface Listener {
void success(BaseModel baseModel);
void fail(String message);
}
Create Base model class
public class BaseModel implements Serializable {
private static final long serialVersionUID = 1L;
}
Call below method inside your onClick mehtod.
protected void userLoginData(final String userName) {
// if you want to pass multiple data to server like string or json you can pass in this constructor
UserLoginLoader userLoginLoader = new UserLoginLoader(LoginActivity.this, userName, "1234567899", new Listener() {
#Override
public void success(BaseModel baseModel) {
// here you got response in object you can use in your activity
UserLoginModel userLoginModel = (UserLoginModel) baseModel;
// you can get data from user login model
}catch(Exception exception){
exception.printStackTrace();
Utils.showAlertDialog(LoginActivity.this, "Server is not responding! Try Later.");
}
}
#Override
public void fail(String message) {
}
});
userLoginLoader.execute();
}
:- User Login Loader class
public class UserLoginLoader extends AsyncTask<String, Void, Boolean> {
private Dialog dialog;
private Listener listner;
private String deviceId;
Activity activity;
String message;
String userName;
boolean checkLoginStatus;
public UserLoginLoader(Activity activity,String userName, String deviceId, Listener listener) {
this.listner = listener;
this.userName =userName;
this.activity = activity;
this.deviceId = deviceId;
}
#Override
protected Boolean doInBackground(String... arg0) {
//User login web service is only for making connection to your API return data into message string
message = new UserLoginWebService().getUserId(userName, deviceId);
if (message != "null" && !message.equals("false")) {
return true;
}
return false;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new Dialog(activity, R.style.CustomDialogTheme);
dialog.setContentView(R.layout.progress);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
BaseModel baseModel = null;
if (!message.equals("null") && (!message.equals("false")) )
baseModel = parseData(message, result);
if (dialog.isShowing()) {
dialog.dismiss();
dialog.cancel();
dialog = null;
}
if (listner != null) {
if (result && baseModel != null)
listner.success(baseModel);
else
listner.fail("Server not responding! Try agian.");
} else
listner.fail("Server not responding! Try agian.");
}
//call parser for parsing data return data from the parser
private BaseModel parseData(String responseData, Boolean success) {
if (success == true && responseData != null
&& responseData.length() != 0) {
UserLoginParser loginParser = new UserLoginParser(responseData);
loginParser.parse();
return loginParser.getResult();
}
return null;
}
}
This is you Login parser class
public class UserLoginParser {
JSONObject jsonObject;
UserLoginModel userLoginModel;
/*stored data into json object*/
public UserLoginParser(String data) {
try {
jsonObject = new JSONObject(data);
} catch (JSONException e) {
Log.d("TAG MSG", e.getMessage());
e.printStackTrace();
}
}
public void parse() {
userLoginModel = new UserLoginModel();
try {
if (jsonObject != null) {
userLoginModel.setUser_name(jsonObject.getString("user_name")== null ? "": jsonObject.getString("user_name"));
userLoginModel.setUser_id(jsonObject.getString("user_id") == null ? "" : jsonObject.getString("user_id"));
userLoginModel.setFlag_type(jsonObject.getString("flag_type") == null ? "" : jsonObject.getString("flag_type"));
} else {
return;
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
/*return ship name list which is stored into model */
public UserLoginModel getResult() {
return userLoginModel;
}
}
Write a callback method in the Activity that takes in the argument that you wish to pass from AsyncTask to that Activity. Send reference to the Activity to AysncTask while creating it. From doInBackground() method make a call to this callback method with the data your API returns.
Code would be something like -
public class TestAsyncTask extends AsyncTask<Integer, Integer, String[]> {
Activity myActivity;
public TestAsyncTask(Activity activity) {
this.myActivity = activity;
}
#Override
protected String[] doInBackground(Integer... params) {
String data = yourApi();
myActivity.callback(data);
}
}
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
new TestAsyncTask(this).execute(someId);
}
public void callback(String data) {
//process data
}
}
Just for the record you can directly get return value from doInBackground() method by calling get() on it.
String data = new TestAsyncTask(this).execute(someId).get();
But note this may block your UI thread as it will wait for the doInBackground() method to complete it's execution.

Wait for all the AsyncTask called in a loop are finished?

I'm calling async tasks in a loop on the onPostExecute() of an asyncTask. I want the control to wait until response of all the tasks is not receieved cause I'm collecting the response in a single arrayList which i have to pass a callback method after all the asyncTasks called in the loop are finished.
I'm avoiding to use the AsyncTask.get() as it blocks the main thread.
public class CallServerAsync extends AsyncTask<AsyncHttpRequestBo, Void, ArrayList<ArrayList<AsyncHttpRequestBo>>> implements PlatwareResponseListener {
PlatwareClientCommonUtils clientCommonFunctions;
Context context;
String url;
PlatwareResponseListener listener;
private ProgressDialog progressDialog;
ArrayList<AsyncHttpResponseBo> processResponseList = null;
ArrayList<AsyncHttpResponseBo> responseList = null;
public CallServerAsync(Context context, PlatwareResponseListener listener) {
this.context = context;
clientCommonFunctions = new PlatwareClientCommonUtils(context);
url = clientCommonFunctions.getServerUrlPrimary();
this.listener = listener;
responseList = new ArrayList<AsyncHttpResponseBo>();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(context, "Please wait", "Downloading...");
}
#Override
protected ArrayList<ArrayList<AsyncHttpRequestBo>> doInBackground(AsyncHttpRequestBo... params) {
ArrayList<ArrayList<AsyncHttpRequestBo>> requestLists = clientCommonFunctions.generateRequestList(params);
return requestLists;
}
#Override
protected void onPostExecute(ArrayList<ArrayList<AsyncHttpRequestBo>> result) {
for (ArrayList<AsyncHttpRequestBo> httpRequestList : result) {
CallserverSubAsync callserverSubAsync = new CallserverSubAsync(context, this);
callserverSubAsync.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, httpRequestList);
// ArrayList<AsyncHttpResponseBo> processResponseList = null;
// try {
// processResponseList = callserverSubAsync.get();
// } catch (InterruptedException e) {
// e.printStackTrace();
// } catch (ExecutionException e) {
// e.printStackTrace();
// }
}
listener.onAsyncTaskCompleted(responseList, listener);
progressDialog.dismiss();
super.onPostExecute(result);
}
#Override
protected void onCancelled() {
progressDialog.dismiss();
super.onCancelled();
}
#Override
public void onAsyncTaskCompleted(ArrayList<AsyncHttpResponseBo> responseList, PlatwareResponseListener listener) {
if (listener instanceof CallServerAsync) {
processResponseList = responseList;
for (AsyncHttpResponseBo responseBo : processResponseList) {
this.responseList.add(responseBo);
}
}
}

Categories

Resources