Android Java AsyncTask work externally - java

I'm new in Java/Android and I come from c#. I've been taking a look into it and testing I found that when I execute an AsyncTask the mainthread keeps executing while the external task is doing it's work. I even found that I can only set the asynctask that execute an external task from the MainActivity.
My problem is that I want to execute an external class that when finished brings back the results(just like c#) to the maintask without setting the async class in the MainActivity.
So.. in code should be something like:
MainActivity.java
public onClickButton(View view) {
String result = SecondaryClass.DoAsyncTask();
}
SecondaryClass.java
private class DoAsyncTask extends AsyncTask<Long, Integer, Integer>
{
#Override
protected Integer doInBackground(Long... params) {
String longString = ThirdAPIClass.GiveMeSomeCode(); //Or work here
return lognString;
}
#Override
protected void onPostExecute(String result) {
return result; //Somehow(?)
}
}
Any idea if there is something similar in Java/Android(?)
PD: I use AsyncTask as an example, I don't know if there is another instruction that do the same or something like that.

Class Singnature:
First Note is that if your result is a String then you need to change your extend clause to:
class DoAsyncTask extends AsyncTask<Long, Integer, String>
Communicating with calling activity:
The AsyncTask's onPostExecute signature is void and it doesn't return data. The most common practices are:
To have this class as an inner class inside your activity, and onPostExecute you can call a method inside that activity.
Add a constuctor to you asyncTask class and pass the activity to it and then call the method using that instance of activity.
First Approach:
#Override
protected void onPostExecute(String result) {
someMethodInMainActivity(result);
}
Second Approach:
public class DoAsyncTask extends AsyncTask<Long, Integer, String>
{
YouActivityName _activity;
public DoAsyncTask(YouActivityName activity)
{
_activity = activity;
}
#Override
protected String doInBackground(Long... params) {
String longString = ThirdAPIClass.GiveMeSomeCode(); //Or work here
return lognString;
}
#Override
protected void onPostExecute(String result) {
if(_activity != null) {
_activity.someMethodInMainActivity(result);
}
}
}
Then you create your AsynTask using :
new DoAsyncTask(this);

Related

AsyncTask - How can i pass an object as parameter to an anonymous AsyncTask class

I am doing some coding stuff with android. Nearly I faced a problem and to solve this I need an anonymous AsyncTask class to execute. But I also need to pass and object to this class before execution. I tried the below code but it's not working and I did not find any solution by googling also.
public void saveCartToRoom(CartsPay cartsPay){
new AsyncTask<Void,Void,Void>(){
CartsPay cartsPay;
#Override
protected Void doInBackground(Void... voids) {
return null;
}
public void setRQ(CartsPay cartsPay){
this.cartsPay= cartsPay;
}
}.setRQ(cartsPay).execute();
}
Here is how to pass a CartsPay parameter to an anonymousAsyncTask
new AsyncTask<CartsPay,Void,Void>(){
CartsPay cartsPay;
#Override
protected Void doInBackground(CartsPay... params) {
this.cartsPay = params[0];
// Your code ...
return null;
}
public AsyncTask setRQ(CartsPay cartsPay){
this.cartsPay= cartsPay;
return this;
}
}.execute(cartsPay);
You can just do it like that:
class CustomAsyncTask extends AsyncTask<Void, Void, Void> {
private YourParam mParam;
public CustomAsyncTask(YourParam param) {
mParam = param;
}
#Override
protected doInBackground(Void.. voids){
//do your thing.
}
}
And then using it:
new CustomAsyncTask(param).execute();

How can i return variable "realImage" which is within onComplete method?

I've created an Asynctask in an activity and now i want to return the variable "realimage" to that Asynctask but i cant seem to access it...
public class PhotoUtils
{
public static Photo getImage(String id)
{
unsplash.getPhoto(id, new Unsplash.OnPhotoLoadedListener()
{
#Override
public void onComplete(Photo photo)
{
Photo realImage=photo;
}
#Override
public void onError(String error)
{
}
});
return realImage; //This line shows error that cannot resolve symbol
realImage
}
}
This is my Async Task which is in the other activity
public class ImageTask extends AsyncTask<Photo,Void,Photo>
{
#Override
protected Photo doInBackground(Photo... photos)
{
Intent intent=getIntent();
Bundle bd=intent.getExtras();
String getId = (String) bd.get("id");
Photo finalPhoto=PhotoUtils.getImage(getId);
return finalPhoto;
}
#Override
protected void onPostExecute(Photo finalPhoto) {
tv1.setText(finalPhoto.getId());
super.onPostExecute(finalPhoto);
}
}
First, looks like you don't even need an Asynctask. Look at the example code
Secondly, you can't return it like that.
OnPhotoLoadedListener is an asynchronous callback.
Just use the image as normal within onComplete.
If you needed to pass back the image to the calling method, extract the callback to a parameter.
// this is void now
public static void getImage(String id, Unsplash.OnPhotoLoadedListener listener) {
unsplash.getPhoto(id, listener);
});
Call this as
PhotoUtils.getImage(id, new Unsplash.OnPhotoLoadedListener() {
// Use image in here
});
Which, if you look closely, all you did was replace normal usage of unsplash.getPhoto with PhotoUtils.getImage, which may be want you want, but you could accomplish a similar approach with a singleton pattern around the unsplash instance variable. That way, you're not rewriting all of Unsplash API calls

Getting data from async task onpostexecute using interface

Hi I am trying to get an arraylist of data from a an async task class to another main class:
I was following the answer below but I am a little lost:
How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?
So I have my class that extends async task and calls to the database to get my object array:
public class GetVideoInfoFromDataBase extends AsyncTask {
// Paginated list of results for song database scan
static PaginatedScanList<AlarmDynamoMappingAdapter> results;
// The DynamoDB object mapper for accessing DynamoDB.
private final DynamoDBMapper mapper;
public interface AlarmsDataBaseAsyncResponse {
void processFinish(PaginatedScanList<AlarmDynamoMappingAdapter> output);
}
public AlarmsDataBaseAsyncResponse delegate = null;
public GetVideoInfoFromDataBase(AlarmsDataBaseAsyncResponse delegate){
mapper = AWSMobileClient.defaultMobileClient().getDynamoDBMapper();
this.delegate = delegate;
}
#Override
protected Object doInBackground(Object[] params) {
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
results = mapper.scan(AlarmDynamoMappingAdapter.class, scanExpression);
return results;
}
#Override
public void onPostExecute(Object obj) {
delegate.processFinish(results);
}
}
There are no errors but I think I have done something incorrectly in it causing my error.
So in my main activity to call the results I have:
GetVideoInfoFromDataBase asyncTask =new GetVideoInfoFromDataBase(new GetVideoInfoFromDataBase.AlarmsDataBaseAsyncResponse(){
#Override
public void processFinish(PaginatedScanList<AlarmDynamoMappingAdapter> output) {
}
}).execute();
I have two problems here
I am getting the error:
"incompatible types: AsyncTask cannot be converted to GetVideoInfoFromDataBase"
In the mainactivity where i have:
`new GetVideoInfoFromDataBase(new GetVideoInfoFromDataBase.AlarmsDataBaseAsyncResponse()`
it wants me to cast it like this:
(GetVideoInfoFromDataBase) new GetVideoInfoFromDataBase(new GetVideoInfoFromDataBase.AlarmsDataBaseAsyncResponse()
That doesn't seem right but I thought i would check.
I am not sure how to return the result when overriding the onprocessfinished.
Thanks in advance for your help
First create an Interface
public interface AsyncInterface {
void response(String response);
}
Assign it in the asynctask class as below :-
Context context;
Private AsyncInterface asyncInterface;
AsyncClassConstructor(Context context){
this.context = context;
this.asyncInterface = (AsyncInterface) context;
}
Then inside onPostExecute method of asynctask class :-
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
asyncInterface.response(s);
}
Then implement this interface in your activity :-
class MainActivity extends AppCompatActivity implements AsyncInterface {
and then import the method of asyncInterface
#Override
public void response(String response) {
//Here you get your response
Log.e(TAG, response);
}
Modify Constructor of class.
Need default constructor. By the way, create method to set Interface.
public void setInterface(AlarmsDataBaseAsyncResponse delegate){
this.delegate = delegate;}
In MainActivity, push your logic in:
object.setInterface(new AlarmsDataBaseAsyncResponse(){
#Override
public void processFinish(PaginatedScanList<AlarmDynamoMappingAdapter> output) {
//your logic
}
});

android call public method and get on success feedback

i have a MainActivity, where i call the public function of another class.
MainActivity:
Sync.StartSync();
Snyc.php
public class Sync {
static void StartSync() {
Boolean onSuccess = false;
// DO HTTP POST REQUEST
if (response == true) {
onSuccess = true;
}
}
}
But i would like to give the onSuccess variable back to the MainActivity, to check if the result of StartSync() is true or false
Is there an way?
You can use AsyncTask and Brodcast.
In MainActivity register broadcastreceiver .
Complate task send broadcast
private class myTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
}
#Override
protected void onPostExecute(String result) {
sendBrodcast();
}
}
You can make the method return a value. Change the
static void StartSync() ..
into
static boolean StartSync()..
and then return a value from it, something like:
return onSuccess;

Android Async http requests, should I make three different classes?

I'm a beginner in Java and coding for Android. When I was coding an app which makes some network requests, I got NetworkOnMainThreadException exception. I googled and found out the reason and solution. But I still have a question. My app makes requests on different sites and will does different actions with responses (first response on login action, it will be checked, second action is some api calls, third action is requesting images), I think I should not make three different classes for each case (doInBackground is the same, but different onPostExecute methods will be here). How can I fix this problem? Thanks
You can pass an aditional variable as doInBackground Params, save it as "global" class variable and switch in onPostExecute so u dont have to make 3 different classes
Like this
public class Async_DL extends AsyncTask<String, String, String> {
String type_of_request;
String url;
#Override
protected void onPreExecute(){
}
#Override
protected String doInBackground(String... params) {
this.url = params[0];
this.type_of_request = params[1];
doinBackground stuff....
}
#Override
protected void onPostExecute(String result) {
switch(this.type_of_request){
case a:
do some stuff
break;
}
}
}
One solution would be to create an interface callback like this
interface Callback {
public void call (String response); //or whatever return type you want
}
Then you might extends your AsyncTask class like this
private class HttpTask extends AsyncTask <Void,Void,String> {
Callback callback;
HttpTask (Callback callback) {
this.callback = callback;
}
// your doInBackground method
#Override
protected void onPostExecute (String response) {
callback.call(response);
}
}
Then you might call your AsyncTask like this
new HttpTask (new Callback () {
#Override
public void call (String response) { /* Here goes implementation */ }
}).execute();
You dont need to make three separate classes for each action. You can extend only once the AsyncTask and i would suggest to add an interface call which can be implemented by your activity:
public interface RequestListener {
public void onLoginCall();
public void onApiCall();
public void onImageCall();
}
At the same time create an enumeration to hold the requests' types:
public enum RequestType{
LOGIN,
API,
IMAGE;
}
Meanwhile you can extend the AsyncTask and call the necessary listener's methods per each case. You can use the second attribute to hold the type of the request:
public class RequestTask extends AsyncTask<Object, RequestType, Object> {
private RequestListener listener;
#Override
protected void onPreExecute(){
}
#Override
protected String doInBackground(Object... params) {
this.url = params[0];
this.type_of_request = params[1];
doinBackground stuff....
}
#Override
protected void onPostExecute(Object result) {
if(result is from login)
listener.onLoginCall();
... and so on
}
}

Categories