I have to load XML data in my app, I'm doing that in a subclass of my activity class extending AsyncTask like this :
public class MyActivity extends Activity {
ArrayList<Offre> listOffres;
private class DownloadXML extends AsyncTask<Void, Void,Void>
{
protected Void doInBackground(Void... params)
{
listOffres = ContainerData.getFeeds();
return null;
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_liste_offres);
DownloadXML.execute(); // Problem here !
for(Offre offre : listOffres) { // etc }
}
}
I don't know how to use execute() here, I have the following error :
Cannot make a static reference to the non-static method execute(Integer...)
from the type AsyncTask
I guess some parameters but what ?
Thank you.
You need to create an instance of your DonwloadXML file and call execute() on that method:
DownloadXML task=new DownloadXML();
task.execute();
EDIT: you should probably also return the listOffers from your doInBackground() and process the array in the onPostExecute() method of your AsynTask. You can have a look at this simple AsyncTask tutorial.
you should call it like:
new DownloadXML().execute();
Actually you are calling the method of AsyncTask (which further extends the AsyncTask class) without making an OBJECT of that class.
you can call the execute method in two ways.
make an object/instance of the class like
DownloadXML task=new DownloadXML();
task.execute();
by using an flying object.
new DownloadXML().execute();
I prefer to use here 2nd method to do that.
Well if you want to execute some code by async task in java you can also do this:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
// add code which you want to run in background thread
runOnUiThread(new Runnable() {
#Override
public void run() {
// add code which you want to run in main(UI) thread
}
});
}
});
And in kotlin if you are using anko, there is much more simpler way to acheive this:
doAsync {
// add code which you want to run in background thread
uiThread {
// add code which you want to run in main(UI) thread
}
}
u can execute ur asynctask either
new DownloadXML().execute();
or
DownloadXML task=new DownloadXML();
task.execute();
and one more thing u are getting in array in asynctask than it is good to use postexeceute method for ur for loop iteration
as given below
protected void onPostExecute(String s) {
for(Offre offre : listOffres) { // do ur work here after feeling array }
}
You have to create object of DownloadXML class first.
DownloadXML downloadxml= new DownloadXML();
downloadxml.execute();
and return listOffres.
listOffres = ContainerData.getFeeds();
return listOffers;
Related
I'm implementing an app that uses many methods that requires an AsyncTask with a waiting dialog.
Actually my approach is to use every time an inner class that extends AsyncTask
something like
private class AsyncOperation extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute(){
pDialog = new ProgressDialog(CurrencyConverterActivity.this);
pDialog.setMessage("Waiting...");
pDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
...
return null
}
protected void onPostExecute(Void params){
pDialog.dismiss();
runOnUiThread(new Runnable() {
public void run() {
//dialogs according status the
//int status is a static variable declared in external class
}
});
}
since with this approach i have to write this inner class too many times and this result in dirty code not well readable, I'm looking for a smarter solution
Could someone help me?
Are you calling the same network each time you use the async task?
If yes, then you can have one class which extends the async and pass the values for each call. You can have response listener to get the response from the method called the async
Something like this:
MainActivity:
First method:
AsyncOperation asyncCall = new AsyncOperation(MainActivity.this, "abc", "bcd");
asyncCall.execute();
Second method:
AsyncOperation asyncCall = new AsyncOperation(MainActivity.this, "aaa", "bbb");
asyncCall.execute();
callback(…){
}
Async Class:
private class AsyncOperation extends AsyncTask<Void, Void, Void> {
AsyncOperation(listener, string, string)
{
}
#Override
protected void onPreExecute(){
pDialog = new ProgressDialog(CurrencyConverterActivity.this);
pDialog.setMessage("Waiting...");
pDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
...
return null
}
protected void onPostExecute(Void params){
pDialog.dismiss();
listener.callback(…);
}
You can create an AsyncTask in a separate file (not as an inner class) and reuse it many times. AsyncTask doesn't have to be an inner class.
You may need to modify your AsyncTask to take additional parameters if needed to make it reusable.
You can also create a constructor for your AsyncTask with parameters for the values you need to pass into it and use that constructor to instantiate your AsyncTask.
This approach makes sense if the way you use AsyncTasks in different places is the same or at least similar. If you use completely different code in each AsyncTask, you will be better off with separate AsyncTasks (though you may still extract them into separate classes from inner classes).
I am starting an AsyncTask from an Activity. When, the AsyncTask completes its execution I need to send a broadcast which needs to call Activity method to update the UI.
Any good approach to achieve this.
Yes.
If the AsyncTask is an inner class of your Activity then it has access to any member variables and your Activity methods. If it isn't then you can simply pass variables to its constructor or even a reference to the Activity to call Activity methods from onPostExecute(). Without any code its hard to say much else.
To pass an instance of your Activity and use its methods if its a separate class then you can create a constructor and do something like
public class MyTask extends AsyncTask<...> // add your params
{
private MyActivity activty;
public MyTask (MyActivity act)
{
this.activty = activty;
}
// ...
}
and in onPostExecute() add something like
activity.myMethod();
and call the task like
MyTask task = new MyTask(this); // pass a reference of the activity
task.execute(); // add params if needed
If the AsyncTask is a separate file from the Activity then you can see this answer on how to use an interface for a callback
Please use Interface.
interface INotifyChange {
void notifyChange(); // You can use params to transfer data :D
}
In Activity you should implements this interface.
YourActivity extends Activity implements INotifyChange {
#Override
public void notifyChange() {
// Right here, you can Update UI.
}
}
When you create new instance of AsyncTask
Example:
YourAsyncTask mTask = new YourAsyncTask(this); // You put INotifyChange
In YourAsyncTask
private INotifyChange iNotifyChange;
public YourAsyncTask(INotifyChange iNotifyChange) {
this.iNotifyChange = iNotifyChange;
}
// When you complete doInBackground or anywhere you want to Update UI please use iNotifyChange.notifyChange()
Example:
#Override
public void onPostExecute(ResultType mResult) {
iNotifyChange.notifyChange();
}
By this way I often use to update progress bar. In this case, I use parameter in my method:
Example:
iNotifyChange.notify(progress);
Have you considered overwriting the onPostExecute() method of the AsyncTask to update the UI? Try something like this:
AsyncTask<String, Void, Bitmap> task = new AsyncTask<String, Void, Bitmap>(imageView)
{
private ImageView imageView;
public AsyncTask(ImageView imageView)
{
this.imageView = imageView;
}
#Override
protected Bitmap doInBackground (String... params)
{
if(params.length > 0)
{
String filePath = params[0];
// Load Bitmap from file
return bitmap;
}
}
#Override
protected void onPostExecute(Bitmap result)
{
imageView.setImageBitmap(result);
}
}
task.execute(filePath);
I have implemented the 2 asyn tasks, I am using android4.0. where one asyntask is executed continuously, second one is executed based on requirement(may be mulitpe times).
For example.
class AsynTask1 exetends AsyncTask<Void, Bitmap, Void>{
protected Void doInBackground(Void... params) {
while(true){
publishProgress(bmp);
}
}
}
class AsynTask2 extends AsyncTask<String, Void,Void>{
protected Void doInBackground(String... params){
System.out.println(params[0])
}
}
In activity class
class MainActivity extends Activity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new AsynTask1().execute();
int i=0;
while(i<100)
{
if(i%2==0)
new AsynTask2().execute("no is even"+i);
i++
}
}
}
In the above case the AsynTask2 is not executed .
If tried with executeOnExecutor(AsyncTask.THREAD_POOL_Executor,params), then both asyntask are executed and I am getting the print messages from the AsynTask2, but those are not in order(like 0 2 6 4 10 8 12 14 ....).
Is there any way to execute the AsynTask1 continuously and AsynTask2 in Sequential order so that the order(like 0 2 4 6 8 10 12 14....) is prevented.
Thanks & Regards
mini.
Use SERIAL_EXECUTOR for Asynctask2
new AsynTask2().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR ,"no is even"+i)
Edit:
Use for Asynctask1 , so that same executor is not used
new AsynTask1().executeOnExecutor(AsyncTask.THREAD_POOL_Executor,params);
You are not supposed to use AsyncTask for long-running threads (the way you are implementing AsyncTask1). See the documentation: http://developer.android.com/reference/android/os/AsyncTask.html . Just create a separate thread for what AsyncTask1 is doing.
Since you need serial execution for what you are doing in AsyncTask2 can be done by creating a ThreadPool of size 1.
// Creating ThreadPool
ExecutorService service = Executors.newFixedThreadPool(1);
// Submitting task
service.execute(task);
// Shutting down the thread pool when not required.
service.shutdown();
Try using call backs. Define the interfaces in your AsyncTask classes and implement them in the main class. Use the callBack on onPostExecute of AsyncTask2 to launch the next AsyncTask2. You'll guarantee the order.
class AsyncTask2 extends AsyncTask<String, Void,Boolean<{
//Your code. doInBackground must now return a boolean.
protected Void onPostExecute(final Boolean success){
myCallback listener = (myCallback) parentActivity;
listener.call();
}
public Interface myCallback{
void call();
}
}
And then on your main activity you implement myCallback.
[EDIT]
Here's a sample of what you could do.
Class MainActivity extends Activity implements myCallback{
//Your code
public void call(){
new AsyncTask2().execute("no is even" + i);
}
}
int i=0;
while(i<100)
{
new AsynTask1().execute();
if(i%2==0)
{
new AsynTask2().execute("no is even"+i);
}
i++
}
I am developing an application in which i need to send the value of the asynctask's onPostExecute method's result in to the previous activity , ie the activity in which the aync task is being called.pls put some codes. Anyhelp is appreciated
Two ways:
Declare class extending AsyncTask as private class in parent Activity
Pass Handler or Activity itself as param of class extending AsyncTask
If I were you, I'd follow the first option.
Look at DOCS:
class MyActivitySubclass extends Activity {
function runOnPostExecute(){
// whatever
}
private class MyTask extends AsyncTask<Void, Void, Void> {
void doInBackground(Void... params){
// do your background stuff
}
void onPostExecute(Void... result){
runOnPostExecute();
}
}
}
Note 1
Code placed in body of function onPostExecute is already run on Activity thread, you should just mention that this keywords leads to MyTask.this and not MyActivitySubclass.this
Well if your AsyncTask is an inner class, you could simply call a method in your activity from onPostExecute():
public class MyActivity extends Activity {
public void someMethod(String someParam) {
// do something with string here
}
public class InnerTask extends AsyncTask<...> {
protected void onPostExecute(result) {
someMethod(Send parameters);
}
}
}
The onPostExecute method is fired on the main UI thread, so anything done there is already on the AsyncTasks caller.
http://developer.android.com/reference/android/os/AsyncTask.html
Fire an event in the OnPostExecute.
Its an add on to the answer by Marek Sebera, he pointed to use a handler. To keep the code simple and intuitive use an interface. This isn't alien concept, we use it all the time for callback functions (eg: OnClickListner etc..). The code would look some thing like this.
public class InnerTask extends AsyncTask<...>
{
interface ResultHandler
{
void gotResult(<> result);
}
private ResultHandler myResult;
//constructor
public InnerTask(....params...,ResultHandler callback)
{
...
this.myResult = callback;
}
protected void onPostExecute(<>result)
{
...
myResult.gotResult(result);
}
}
public class MyActivity extends Activity implements InnerTask.ResultHandler
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
//do something
//if you want the InnerTask to execute here
InnerTask i = new InnerTask(....params...,this); //send 'this' as parameter
i.execute();
}
#Override
public void gotResult(<> result)
{
//from onPostExecute
}
}
If we want to use the same AsynTask class at multiple sites we can use this type of implementation instead of using nested classes implementation.
I am facing problem of having one async task, but I need it use twice, because each time I change different part of GUI (updating progress bar).
Is there any way how to determine in if - else clause, which activity does it call and then make appropriate function for each of both of them?
Edit: huh, answer was here and now there isn't...
Thanks
You can hold a member variable which contains the activity/context it is started from.
//pseudocode
AsyncTask task = new AsyncTask();
task.mActivity = this;
task.execute();
Inside doInBackground just check the activity:
//pseudocode
if (mActivity instanceof MyActivity) {
// ....
} else {
// ....
}
Extract the code from the AsyncTask implementation and delegate that to the Activity. Example:
public interface MyDelegate {
public void updateProgress(....)
}
Your AsyncTask takes a delegate and calls it when appropiate:
public class MyAsyncTask .... {
public MyAsyncTask(MyDelegate myDelegate) { ... }
// somewhere in your code (probably onProgressUpdate)
myDelegate.updateProgress(...)
}
Your Activity/ies implement/s the delegate:
public class MyActivity extends Activity implements MyDelegate {
public void updateProgress(...) {
// update ui
}
// somewhere in your code:
new MyAsyncTask(this).execute(...);
}