I have been working with passing the result created by the onPostExecute of AsyncTask in Fragment.
I know how to do it in Activity, like ((MyActivity)context).someMethod();
But how can I do this in Fragment?
I do ((MyFragment)contextOfAsyncTask).methodInFragment() but it gives me an error "Cannot cast from Context to MyFragment".
Here is my code in AsyncTask
class AsyncMethod extends AsyncTask{
ArrayList<MyObject> myVar= new ArrayList<MyObject>();
String result;
ListView lv;
Context contextOfAsyncTask;
public AsyncMethod(Context xc, ListView xl){
contextOfAsyncTask= xc;
lv = xl;
}
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void...param) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(http://www.myurl.com/something.php);
HttpResponse httpResponse = httpclient.execute(httppost);
HttpEntity httpEntity = httpResponse.getEntity();
result = EntityUtils.toString(httpEntity);
return null; //EVERYTHING IS WORKING FINE HERE, AND I CAN GET THE VALUE
}
#Override
protected void onPostExecute(Void res) {
//it does not work here
((MyFragment)contextOfAsyncTask).methodInFragment(result);
}
It is look like you want to call method from AsyncTask
class YourTask extends AsyncTask<Void, Void, Void> {
private SomeFragment fragment;
YourTask(SomeFragment fragment) {
this.fragment = fragment;
}
#Override
protected Void doInBackground(Void... params)
{
//do whatever you want to do
}
#Override
protected void onPostExecute(Void res)
{
fragment.yourmethod();
}
}
i hope it help..
Related
I am trying to make a GET request on a URL, I created a class extending AsyncTask<Void, Void, Void> and I try to call new MyClass.execute() ... I have done this before and it worked, today it is not working. What am I doing wrong?
Here is my code:
public class SignUpActivity extends AppCompatActivity {
String TAG = SignUpActivity.class.getSimpleName();
String URL;
ArrayList<String> countries = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up);
new MyClass.execute();
}
private class MyClass extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
//TODO
}
#Override
protected Void doInBackground(Void... params) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(URL, "GET");
//Handling response in jsonStr code
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//TODO
}
}
This is a syntax error. It should be
new MyClass().execute();
not as new MyClass.execute();
use this to get data use return to return value:
public class SignUpActivity extends AppCompatActivity {
String TAG = SignUpActivity.class.getSimpleName();
String URL;
ArrayList<String> countries = new ArrayList<>();
String jsonStr="";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up);
String response = new MyClass.execute();
}
private class MyClass extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
//TODP
}
#Override
protected String doInBackground(Void... params) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(URL, "GET");
//Handling response in jsonStr code
return jsonStr;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//TODO
jsonStr = result;
}
}
}
public class JsonHandler {
static String response = null;
public final static int GET = 1;
public final static int POST = 2;
public JsonHandler() {
}
public String makeServiceCall(String url,int method) {
return this.makeServiceCall(url, method, null);
}
public String makeServiceCall(String url, int method,
List<NameValuePair> params) {
try {
// http client
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
// Checking http request method type
if (method == POST) {
HttpPost httpPost = new HttpPost(url);
if (params != null) {
httpPost.setEntity(new UrlEncodedFormEntity(params));
}
httpResponse = httpClient.execute(httpPost);
} else if (method == GET) {
if (params != null) {
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
}
HttpGet httpGet = new HttpGet(url);
httpResponse = httpClient.execute(httpGet);
}
httpEntity = httpResponse.getEntity();
response = EntityUtils.toString(httpEntity);
} catch (Exception e) {
}
return response;
}
}
Add above class to your main package and do it as doInBackground
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
JsonHandler json = new JsonHandler();
String jsonStr = json.makeServiceCall(params[0], JsonHandler.GET);
// parse your json data here
}
I'm working on a basic android app that makes a POST with HttpURLConnection. I want to return the response Message from my Web API.
My MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView mTextView = findViewById(R.id.textView);
AsyncExample asyncExample = new AsyncExample();
asyncExample.execute();
mTextView.setText(asyncExample.getResponseMsg());
}
}
My AsyncExample.java
class AsyncExample extends AsyncTask<Void, Void, Void> {
private HttpURLConnection con;
private String responseMsg;
protected void onPreExecute() {
responseMsg = "empty message";
}
#Override
protected Void doInBackground(Void... params) {
String urlParameters = "param1=data1";
byte[] postData = urlParameters.getBytes(Charset.forName("UTF-8"));
int postDataLength = postData.length;
String request = "http://192.168.1.30:6262";
URL url = null;
try {
url = new URL(request);
con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setInstanceFollowRedirects(false);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("charset", "utf-8");
con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
responseMsg = con.getResponseMessage();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public String getResponseMsg() {
return responseMsg;
}
}
After running the app, i get empty message in my TextView. Why it is not getting updated my doInBackground? Even if con.getResponseMessage() is null, it should be updated?
The problem is that your AsyncTask is executed asynchronously, while you try to retrieve the value immediately. You need to implement this a little bit differently. Either leverage the API of AsyncTask, sine it posts callbacks for your on the UI thread. You can update your TextView directly in your AsyncTask
class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
myTextView.setText("progress started");
}
#Override
protected String doInBackground(final Void... voids) {
String s = amazingCallToBackend();
return s;
}
#Override
protected void onPostExecute(final String s) {
myTextView.setText(s);
}
}
Or if you just want the value, you can pass a Callback to your async task that will deliver the value to you, something like that
interface Callback {
void onValueReceived(String value);
void onFailure();
}
class MyAwesomeAsyncTask extends AsyncTask<Void, Void, String> {
private Callback callback;
MyAwesomeAsyncTask(final Callback callback) {
this.callback = callback;
}
#Override
protected String doInBackground(final Void... voids) {
String s = amazingCallToBackend();
return s;
}
#Override
protected void onPostExecute(final String s) {
callback.onValueReceived(s);
}
}
Here's how you create it
Callback callback = new Callback() {
#Override
public void onValueReceived(final String value) {
}
#Override
public void onFailure() {
}
};
new MyAwesomeAsyncTask(callback).execute();
However, be careful because if for some reason your activity/fragment is gone/finished before your AsyncTask is done, this can cause memory leaks.
A quick Google search will tell you all you want about AsyncTask leaking memory :)
Your doInBackground method take time to execute. you are immediately calling mTextView.setText(asyncExample.getResponseMsg()); but asynctask has been not been finished yet. You need to wait until your doInBackground finish and then call that setText you can do it in onPostExecute method.
AsyncTask has 3 default method
1. On preexecute
2. Do in background
3. On post execute
post execute:
The response got from the doinbackground is in the post execute.
Here we can process the result . use the runnable method to update text view ui
Override the onPostExecute() Method to return the text. In the Main Activity create a method to update the TextView after completing the execution of the Async Task. It is coming blank as because the Main Thread is not paused its executing and setting the text View but the Async task has not yet finished executing and hence the String is empty. So wait for the Async Task to finish before setting the text view.
String str_result= new RunInBackGround().execute().get();
Refer to this for more information.
You can do it in a number of ways. I'd try to suggest you a way that would require negligible amount of changes to your existing code.
Declare the mTextView as a Global variable, Override onPostExecute() method inside your AsyncExample and update mTextView inside that onPostExecute() method with the value passed to it by the doInBackground() method [here, notice that responseMsg is returned at the end of doInBackground() ground which is caught as a String value (result) by the onPostExecute() method]. However, I also think that its a good idea to Override your onPreExecute() method.
In order to do so, your MainActivity.java should be as follows:
public class MainActivity extends AppCompatActivity {
TextView mTextView; //declare mTextView outside the onCreate() method as a Global String variable.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.textView);
AsyncExample asyncExample = new AsyncExample();
asyncExample.execute();
}
}
Please make your asynctask an inner-class of the same activity and edit it as follows:
class AsyncExample extends AsyncTask<Void, Void, Void> {
private HttpURLConnection con;
private String responseMsg;
#Override // Its a good practice to Override the onPreExecute() method.
protected void onPreExecute() {
responseMsg = "empty message";
}
#Override
protected String doInBackground(String... params) {
String urlParameters = "param1=data1";
byte[] postData = urlParameters.getBytes(Charset.forName("UTF-8"));
int postDataLength = postData.length;
String request = "http://192.168.1.30:6262";
URL url = null;
try {
url = new URL(request);
con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setInstanceFollowRedirects(false);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("charset", "utf-8");
con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
responseMsg = con.getResponseMessage();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return responseMsg; //return the value of responseMsg
}
#Override //override onPostExecute() method
protected void onPostExecute(String result) { //receive the value to be set to mTextView which is returned by the doInBackground() method.
mTextView.setText(result);
}
}
Try to do like this
MainActivity
public class MainActivity extends AppCompatActivity {
TextView mTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.textView);
AsyncExample asyncExample = new AsyncExample(this,mTextView);
asyncExample.execute();
}
}
AsyncTask
class AsyncExample extends AsyncTask<Void, Void, Void> {
private HttpURLConnection con;
private String responseMsg;
private MainActivity mContext;
TextView mTextView;
public AsyncExample (MainActivity context, TextView textView) {
mContext = context;
mTextView = textView;
}
protected void onPreExecute() {
responseMsg = "empty message";
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
protected Void doInBackground(Void... params) {
String urlParameters = "param1=data1";
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
int postDataLength = postData.length;
String request = "http://192.168.1.30:6262";
URL url = null;
try {
url = new URL(request);
con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setInstanceFollowRedirects(false);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("charset", "utf-8");
con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
responseMsg = con.getResponseMessage();
mContext.runOnUiThread(new Runnable() {
#Override
public void run() {
mTextView.setText(responseMsg);
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public String getResponseMsg() {
return responseMsg;
}
}
I am currently trying to make an android app that basically downloads strings from a url. But I want to make it object oriented. My mainActivity gets string from webService which downloads string when button is clicked. But I am not good at interfaces and callbacks. What should I do to make this code run?
public class MainActivity extends Activity implements WebServiceInterface{
private TextView textView;
private Button readWebPage;
private WebService service;
private WebServiceInterface webServiceInterface;
private String response;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.TextView01);
readWebPage = (Button) findViewById(R.id.readWebpage);
service = new WebService();
readWebPage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
service.execute(new String[]{"http://google.com/"});
onSuccess(response);
}
});
}
#Override
public void onSuccess(String response) {
textView.setText(Html.fromHtml(response));
}
#Override
public void onFail(Exception ex) {
textView.setText(ex.getLocalizedMessage());
}
}
public class WebService extends AsyncTask<String, Void, String> {
private WebServiceInterface webServiceInterface;
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
webServiceInterface.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
webServiceInterface.onFail(e);
}
}
return response;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
public interface WebServiceInterface {
void onSuccess(String response);
void onFail(Exception ex);
}
you need to create one public method for set webServiceInterface in WebService class like
public setWebServiceInterface (WebServiceInterface listener)
{
this.webServiceInterface =listener;
}
in MainActivity activity call this method and pass argument this
service.setWebServiceInterface (this);
in WebService class in onPostExecute Method call
webServiceInterface.onSuccess(s);
Add WebService (WebServiceInterface webServiceInterface) in your AsyncTask as a constructor.
service = new WebService(new WebServiceInterface (){
void onSuccess(String response){
//do your stuff
}
void onFail(Exception ex){
//do your stuff
}
});
and in your asynctask
public class WebService extends AsyncTask<String, Void, String> {
public WebService (WebServiceInterface webServiceInterface){
this.webinterface= webServiceInterface;
}
private WebServiceInterface webinterface;
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
webinterface.onSuccess(response);
} catch (Exception e) {
e.printStackTrace();
webinterface.onFail(e);
}
}
return response;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
I have found the problem, it is because of runOnUiThread is missing.
I have an android app that consist of an activity and a java class that extends AsyncTask. So I have a String in the java class that called resFromServer
which I want to display it in a message in a suitable android widget like Alertdialog .
I want someone to help me in how to access that String from the activity
public class JSONTransmitter extends AsyncTask<JSONObject, JSONObject, JSONObject> {
String url = "http://192.168.1.8:89/Derdeery/b.php";
protected JSONObject doInBackground(JSONObject... data) {
JSONObject json = data[0];
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 100000);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitNetwork().build());
JSONObject jsonResponse = null;
HttpPost post = new HttpPost(url);
try {
StringEntity se = new StringEntity("json="+json.toString());
post.addHeader("content-type", "application/x-www-form-urlencoded");
post.setEntity(se);
HttpResponse response;
response = client.execute(post);
String resFromServer = org.apache.http.util.EntityUtils.toString(response.getEntity());
Log.i("Response from server", **resFromServer**);
}
catch (Exception e)
{ e.printStackTrace();}
return jsonResponse;
}
}
the activity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} }
Proper solution: create an instance of the AsyncTask and make a callback in order to catch the response into any Activity. All Activities which will implement this interface, can retrieve the result of the AsyncTask. This is more flexible and can be used by multiple Activities with just one single AsyncTask.
You have to create the instance and return the String response, in AsyncTask:
public class JSONTransmitter extends AsyncTask<JSONObject, Void, String> {
private AsyncCallback asyncCallback; // callback variable
// constructor
public JSONTransmitter(Context context) {
// attach the callback to any context
asyncCallback = (AsyncCallback) context;
}
// create the interface
public static interface AsyncCallback {
void onResponse(String res);
}
...
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (asyncCallback != null) {
// call the onResponse method for callback
asyncCallback.onResponse(result);
}
}
}
Then, you can implement to any Activity the callback by setting its Context as follows:
public class MainActivity extends Activity implements JSONTransmitter.AsyncCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// set the Context to the AsyncTask when you create it
// in order to return here and execute the request
new JSONTransmitter(this).execute(...);
}
...
#Override
public void onResponse(String res) {
// handle the string response when it's called from onPostExecute()
Log.v("From_MainActivity", "AsyncTask returns this: "+res);
}
}
Therefore, you can do what you want in the Activity with resFromServer (result string) from AsyncTask class.
Pass your activity as parameter to your AsyncTask class constructor :
class MyAsyncTask extends AsyncTask<URL, Integer, Long> {
Activity mActivity;
public MyAsyncTask(Activity activity) {
mActivity = ativity;
}
Then update your activity:
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
int id = mActivity.findViewById(...);
}
You should not use the doInBackground method to update the activity.
Use the onPostExecute because it uses the main Thread.
I'm getting a NullPointerException when I try to request a JSON with AsyncTask. I'm using loopj and AsyncTask
Here's my code:
String str = null;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new TheTask().execute();
}
class TheTask extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
try{
AsyncHttpClient client = new AsyncHttpClient();
client.addHeader("Authorization", "Token token=Wa5sfwP3ku7c15qkZTsd**");
client.get("http://*********.com/api/v1/***", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
str = response;
Log.v("==========RESULT==========", response);
}
});
} catch(Exception e){
Log.v("========== ERROR ==========", e.toString());
}
return str;
}
#Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.textView1);
txt.setText("Result: " + result);
}
}
}
You are doing it wrong.
In your doInBackground() method you should use synchronous methods, and you are using asynchronous:
client.get("http://*********.com/api/v1/***", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
str = response;
Log.v("==========RESULT==========", response);
}
That's why your doInBackground() returns null, and you are trying to deal with null in onPostExecute()
You should use methods from class SyncHttpClient from Loopj-Async library.