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.
Related
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();
I have an asyncTask for making a request to a youtube API. I am trying to return data from the AsyncTask but it freezes as soon as I execute the youtube request
public class FindPreviousPlaylistTask extends AsyncTask<Void, Void, PlaylistListResponse> {
#Override
protected PlaylistListResponse doInBackground(Void... params) {
YouTube.Playlists.List playlistsListMineRequest = getYoutube().playlists()
.list("snippet,contentDetails")
.setMine(true)
.setMaxResults(50L);
ArrayList<Playlist> foundPlaylists = new ArrayList<Playlist>();
PlaylistListResponse response = playlistsListMineRequest.execute(); //Async call
return response;
return null;
}
}
.
private PlaylistListResponse getPlaylist(){
FindPreviousPlaylistTask previousPlaylistTask = new FindPreviousPlaylistTask();
return previousPlaylistTask.execute().get();
}
The whole point of the AsyncTask is make the youtube call outside of the main thread, but now I can't return the value of the youtube call.
If I call previousPlaylistTask.execute() without .get() it works fine
You return result will available in onPostExecute() method or you can create an Interface like this
public class FindPreviousPlaylistTask extends AsyncTask<Void, Void,
PlaylistListResponse> {
public interface AsyncResponse {
void processFinish(PlaylistListResponse output);
}
public AsyncResponse delegate = null;
public FindPreviousPlaylistTask (AsyncResponse delegate){
this.delegate = delegate;
}
#Override
protected PlaylistListResponse doInBackground(Void... params) {
YouTube.Playlists.List playlistsListMineRequest =
getYoutube().playlists()
.list("snippet,contentDetails")
.setMine(true)
.setMaxResults(50L);
ArrayList<Playlist> foundPlaylists = new ArrayList<Playlist>();
PlaylistListResponse response = playlistsListMineRequest.execute();
//Async call
return response;
return null;
}
#Override
protected void onPostExecute(PlaylistListResponse result) {
delegate.processFinish(result);
}
}
you can call it like this
private void getPlaylist(){
FindPreviousPlaylistTask previousPlaylistTask=new
FindPreviousPlaylistTask( new AsyncResponse(){
#Override
void processFinish(PlaylistListResponse output){
//here your AsyncTask response will be available in output valiable
//you can do whatever you want here
}
}).execute();
}
Your app freezes because you are calling get() which makes current thread wait for task to finish and get result. You should instead use the result given in onPostExecure(PlaylistListResponse result).
public class FindPreviousPlaylistTask extends AsyncTask<Void, Void, PlaylistListResponse> {
#Override
protected PlaylistListResponse doInBackground(Void... params) {
YouTube.Playlists.List playlistsListMineRequest = getYoutube().playlists()
.list("snippet,contentDetails")
.setMine(true)
.setMaxResults(50L);
ArrayList<Playlist> foundPlaylists = new ArrayList<Playlist>();
PlaylistListResponse response = playlistsListMineRequest.execute(); //Async call
return response;
return null;
}
#Override
protected void onPostExecute(PlaylistListResponse result) {
// Do something with your result
}
}
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;
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
}
}
I have APIHelper class, whose static methods asynchronously make request to server, receive json string, parse and return Object or ArrayList:
...
public static ArrayList<Item> getItemsInCategory(int id_category) throws ExecutionException, InterruptedException, JSONException {
DoRequest doRequest = new DoRequest();
String jsonString = doRequest.execute(API_PATH + PRODUCT_SEARCH + CATEGORY_ID + id_category).get();
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray("products");
return Item.fromJson(jsonArray);
}
public static Item getItem(int id_item) throws ExecutionException, InterruptedException, JSONException {
DoRequest doRequest = new DoRequest();
String jsonString = doRequest.execute(API_PATH + PRODUCT_GET_INFO + id_item).get();
JSONObject jsonObject = new JSONObject(jsonString);
return Item.fromJson(jsonObject);
}
...
Now I want to make methods without calling get() method from AsyncTask class DoRequest.
My DoRequest class:
public class DoRequest extends AsyncTask<String, Void, String> {
ResultListener mResultListener;
public abstract interface ResultListener{
Object onResultAvailable(String result) throws JSONException;
}
DoRequest(ResultListener resultListener){
mResultListener = resultListener;
}
#Override
protected String doInBackground(String... URL) {
ServiceHandler serviceHandler = new ServiceHandler();
String jsonStr = serviceHandler.makeServiceCall(URL[0]);
return jsonStr;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
mResultListener.onResultAvailable(result);
} catch (JSONException e) {
e.printStackTrace();
}
}
Help me change my methods in APIHelper class that they return values after callback from DoRequest.
You can use an event bus like otto to have the async task publish an event to the event bus once in onPostExecute and then have the whoever the Helper class is returning its results to, listen to the event on the bus and then handle the callback there.
http://square.github.io/otto/
An example of using this would be:
First you are going to have to use a custom post method to be able to post to threads from the background.
public class MainThreadBus extends Bus {
private final Handler handler = new Handler(Looper.getMainLooper());
#Override public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
super.post(event);
} else {
handler.post(new Runnable() {
#Override
public void run() {
post(event);
}
});
}
}
}
Now that we have that set up, inside of the class that calls the helper class we create a register on the bus and call the helper method:
class someClass(){
///some stuff
public void performRestCall(int id_category){
bus.register(this);
ApiHelper.getItemsInCategory(id_category);
}
#Subscribe
public void restCallCompleted(GetCategoryEvent e){
ArrayList<Item> list = e.getList();
//do whatever else you need to
bus.unRegister(this);
}
}
Now in the asyncTask onPostExecute we perform all the work we were doing after the asyncTask finished and tell everyone on the bus that this event has completed. We pass the list in the object instead of return it from a method.:
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
bus.register(this);
try {
JSONObject jsonObject = new JSONObject(jsonString);
bus.post(new GetCategoryEvent( Item.fromJson(jsonObject));
} catch (JSONException e) {
e.printStackTrace();
}
}
Your solution will end up being something along these lines.