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

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
}
}

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();

Is it a good idea to use static or nonstatic? (Android)

I'm working with a simple function that I make to do an HTTP friend request that I call from another static reference. The problem is that the fragment system that google provides (Tab Navigator Activity) the prebuild code does not allow me to use a non-static method in there.
The code which I call the method
enviarsolicitud(param1,param2);
This is the code of the void that I say
private static void enviarsolicitud(final String idadder, final String idadded)
{
class EnviarSolicitudClass extends AsyncTask<String,Void,String>
{
#Override
protected void onPreExecute()
{
super.onPreExecute();
System.out.println("enter");
}
#Override
protected void onPostExecute(String s)
{
super.onPostExecute(s);
if(s.contains("friendrequest")){
String[] friendrequest = s.split(":");
System.out.println(friendrequest[0] + " " + friendrequest[1]);
}
else if (s.contains("friendrequestcant"))
{
}
else
{
}
}
#Override
//En segon pla
protected String doInBackground(String... params)
{
HashMap<String,String> dades = new HashMap<>();
dades.put("idadder",params[0]);
dades.put("idadded",params[1]);
RegisterUserClass ruc = new RegisterUserClass();
String resultat = ruc.sendPostRequest("http://www.myurl.net/friend.php",dades);
return resultat;
}
}
EnviarSolicitudClass esc = new EnviarSolicitudClass();
esc.execute(idadder,idadded);
}
I don't know a lot about non-static and static but the problem is that google use static methods for the prebuilded activity. Do you recommend to use static for this type of voids? I always use non-static methods because static is limited a lot
I don't think this is an issue of static vs non-static.
Your issue is when to write/use an AsyncTask. My suggestion would probably be switch to Volley or OkHttp if you are using HTTP methods, but if you want to continue down this path, read on.
Make an interface
public interface StringCallback {
void onResponse(String result);
}
And add a parameter for a callback result to sendPostRequest that accept the POST response.
private void enviarsolicitud(final String idadder, final String idadded) {
HashMap<String,String> dades = new HashMap<>();
dades.put("idadder",params[0]);
dades.put("idadded",params[1]);
RegisterUserClass ruc = new RegisterUserClass();
ruc.sendPostRequest("http://www.myurl.net/friend.php",dades,new StringCallback() {
#Override
public void onResponse(String response) {
// Continue with UI logic here
}
});
// Can't use HTTP response here
}
And for sendPostRequest, you use the AsyncTask, or whatever HTTP framework you want and "pass back" the response when it returns.
public void sendPostRequest(final String url, final HashMap<String, String> params, final StringCallback callback) {
new AsyncTask<String, Void, String>() {
#Override
public String doInBackground(String... params) {
// TODO: HTTP things
}
#Override
protected void onPostExecute(String s)
{
super.onPostExecute(s);
if (callback != null) {
callback.onResponse(s);
}
return; // Done here
}.execute(params.get("idadder"), params.get("idadded"));
}
The solution for me is:
new HomeActivity().enviarsolicitud(param1,param2);
Last answer by #cricket_007 helps me to improve my code.

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 Java AsyncTask work externally

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);

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;

Categories