I would like to execute the doInBackground() method of AsyncTask inner class of my ArticleListFragment_develop.class from another class. How would i go about doing this. Please can someone help me with the syntax? I have tried a few things and i keep getting errors.
public class ArticleListFragment_develop extends ListFragment {
........
private class DownloadXmlTask extends
AsyncTask<String, Void, ArrayList<Article>> {
/*
* #Override protected void onPreExecute() { pDialog = new
* ProgressDialog(getActivity());
* pDialog.setMessage("Loading search results...");
* pDialog.setIndeterminate(true);
* pDialog.setCanceledOnTouchOutside(false); pDialog.show(); }
*/
#Override
protected ArrayList<Article> doInBackground(String... urls) {
Log.d(TAG, "DownLoadXmlTask Thread id: "
+ Thread.currentThread().getId());
try {
return loadXmlFromNetwork(urls[0]);
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return articles;
}
Write the AsyncTask in a seperate class file and use it.
new DownloadXmlTask().execute();
First read this. Then you have to have OBJECT of your async task. Write public method in your class that will be executing async task and call it. Caller object have to have reference to your fragment object.
It seems that your problem is that the inner class AsyncTask is not visible to any other class.
My suggestion is either bring the AsyncTask out of the ArticleListFragment_develop class, or create a function and call it from outside classes.
Related
I have this asynctask working fine for what I want with a single argument (remove the param2 and it runs) but as soon as I attempt to add the 2nd argument I receive:
Syntax error on token "param2", VariableDeclaratorId expected after this token
which to be honest, I've never come across.
The function is below (havent included the parameters as I know they've worked in other functions and do work when used individually, but as a pair....) I believe I may be trying to add them incorrectly?
Do I need to make them into an array and use the array as a parameter? If so, how would I go about it? (Still getting the hang of android!)
My function
private class LoadList extends AsyncTask<String, Void, ArrayList<List>> {
private Exception exception = null;
/**
* Main worker method
*/
protected ArrayList<List> doInBackground(String... param1, param2) {
try {
//Call web service
return Utils.getWebService(getApplicationContext()).getListInfo(param1[0], param2[1]);
} catch (Exception e) {
exception = e;
return null;
}
}
}
If any more is needed let me know, please, and thank you!
There is two ways to pass a variable to the AsyncTask.doInBackground method:
using it's varargs parameter : String... param. You can add many value to param when calling the execute method:
LoadList loadistTask = new LoadList();
loadistTask.execute(new String[]{"my value","another value"}); After you will access them like this: param[0] , param[1], etc.
The other method is to create a custom constructor and pass your variable to it:
LoadList loadistTask = new LoadList("my var here");
loadistTask.execute();
private class LoadList extends AsyncTask<String, Void, ArrayList<List>> {
private Exception exception = null;
private String myVar;
/**
* constructor
*/
public LoadList(String myVar) {
this.myVar = myVar;
}
/**
* Main worker method
*/
protected ArrayList<List> doInBackground(String... param) {
// this.myVar to access your var in the doInBackground method.
try {
//Call web service
return Utils.getWebService(getApplicationContext()).getListInfo(param[0], param[1]);
} catch (Exception e) {
exception = e;
return null;
}
}
private class LoadList extends AsyncTask<String, Void, ArrayList<List>> {
private Exception exception = null;
/**
* Main worker method
*/
protected ArrayList<List> doInBackground(String... param) {
try {
//Call web service
return Utils.getWebService(getApplicationContext()).getListInfo(param[0], param[1]);
} catch (Exception e) {
exception = e;
return null;
}
}
Try this
You will just need to pass an array of String.
Snippet:
AsyncTask:
private class LoadList extends AsyncTask<String, Void, ArrayList<List>> {
private Exception exception = null;
/**
* Main worker method
*/
protected ArrayList<List> doInBackground(String... params) {
try {
//Call web service
return Utils.getWebService(getApplicationContext()).getListInfo(param1[0], param2[1]);
} catch (Exception e) {
exception = e;
return null;
}
}
}
Call it as:
LoadList loadistTask = new LoadList();
loadistTask.execute(new String[]{"value 1","value 2"});
Hope this helps.
Just call your AsyncTask with several arguments, like this:
new LoadList().execute("value 1", "value 2")
The thing is that the argument String... param can handle any number of arguments and bundles them in an array. See Mahesh's answer on how to use them. If you add another argument after having String... param the compiler won't know when to assign a variable of a call to that argument.
So what you can do technically in Java is foo(String a, String b, String... c) but you can't do foo(String a, String... b, String c).
However, in your case, since doInBackground(String... param) is a predefined method signature you won't be able to add more arguments, because the framework wouldn't be able to call it.
Why, when I change
private class DownloadTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... arg0) {
try {
Downloader.DownloadFromUrl("http://www.sciencemag.org/rss/news.xml", openFileOutput("Sciencemag.xml", Context.MODE_PRIVATE));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result){
mAdapter = new SiteAdapter(MainActivity.this, -1, XmlParser.getSingleItemsFromFile(MainActivity.this));
sitesList.setAdapter(mAdapter);
}
}
to
private void downloadFile(){
try {
Downloader.DownloadFromUrl("http://www.sciencemag.org/rss/news.xml", openFileOutput("Sciencemag.xml", Context.MODE_PRIVATE));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
mAdapter = new SiteAdapter(MainActivity.this, -1, XmlParser.getSingleItemsFromFile(MainActivity.this));
sitesList.setAdapter(mAdapter);
}
i get an error? I just want to call method downloadFile() instead of creating instance of inner class DownloadTask and call execute() of this instance.
The error is telling you that you cannot make network tasks on the main thread.
Look at the Android API where NetworkOnMainThreadException is defined to know more about it.
I hope this helps!
Imagine your method downloadFile() takes too long time - this will block the UI. To prevent this you should use AsyncTask which will do the background operations (downloading your file i guess) and when it is ready will update your UI. In doInBackground() put your downloadFile() method and in onPostExecute() deal with the result. Also be careful what parameters to give to your AsyncTask class.
I've got a simple login screen. If you click "Login", a progress bar should appear while we wait for the AsyncTask in the background to check the login credentials.
If I run the code without the AsyncTask in the background, my progress bar appears immediately. However, if I use the AsyncTask, which I set up after I make my progress bar appear, the app freezes at the exact moment I click on "Login". Then it waits until the AsyncTask has got its result (get() command) and only then it unfreezes, making my progress bar useless.
Is this a commonly known issue? How do you solve it?
This is how where I set up the AsyncTask, after I show the progress bar.
showProgress(true, "Logging in ...");
mAuthTask = new InternetConnection();
String arguments = "email="+mEmail+"&pwd="+mPassword;
boolean k = mAuthTask.makeConnection("ADDRESS", arguments, getBaseContext());
String f = mAuthTask.getResult();
And this is my AsyncTask. downloadUrl() sets up an HttpURLConnection. This works, I tested it.
private DownloadData data = new DownloadData();
public boolean makeConnection(String url, String arguments, Context context) {
if(isWifi(context) || isMobile(context)) {
argsString = arguments;
data.execute(url);
return true;
} else {
return false; //No network available.
}
}
public String getResult() {
try {
return data.get();
} catch (InterruptedException e) {
return "Error while retrieving data.";
} catch (ExecutionException e) {
return "Error while retrieving data.";
}
}
private class DownloadData extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... url) {
try {
return downloadUrl(url[0]);
} catch (IOException e) {
return "Unable to retrieve data.";
}
}
Do it like:
#Override
protected void onPreExecute() {
Asycdialog.setMessage("Working");
Asycdialog.getWindow().setGravity(Gravity.CENTER_VERTICAL);
Asycdialog.getWindow().setGravity(Gravity.CENTER_HORIZONTAL);
Asycdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
Asycdialog.setCancelable(false);
//Dialog Show
Asycdialog.show();
super.onPreExecute();
And then in onPostExecute:
protected void onPostExecute(String result) {
// hide the dialog
Asycdialog.dismiss();
super.onPostExecute(result);
}
To use the same Async task from Different classes:
class MainActivity{
new MyTask().execute();
}
class DifferentActivity {
new MyTask().execute();//a new instance
}
class MyTask extends AsyncTask{
public MyTask(Context context){
}//Pass in context.
}
Pass the context to the constructor, if you want a consistent Progress dialog.
TO publish the progress from doInBackground you can use the following:
publishProgress(progress);
Asycdialog.setMax(lines);
Asycdialog.incrementProgressBy(1);
Where progress is a string, lines are the max number of items.
You should not call get() it blocks the ui waiting for the result to be returned making asynctask no more asynchronous.
You have
private DownloadData data = new DownloadData();
and you have
data.get(); // this why it freezes
and
private class DownloadData extends AsyncTask<String, Void, String>
http://developer.android.com/reference/android/os/AsyncTask.html#get()
You only need
data.execute(url);
And if your asynctask is an inner class of activity class you can return result in doInbackground and update ui in onPostExecute. If not you can use interface as a callback to the activity to return the result.
your issue is related to the fact that you are calling getResult from the UI Thread. getResult calls data.get() that is a blocking operation. That's why you are getting a freeze. Your UI Thread is waiting for get() to complete and it is unable to draw everything else
I have a base class of an activity and a sub class which extends the base class. The superclass has a async task to perform some action. I call this by running it on the ui thread since otherwise it throws an IllegalInitializerError:
superclass.this.runOnUiThread(new Runnable() {
public void run() {
String p="";
try {
p=new asynctasker().execute().get();
}
}
}
In my async task:
protected void onPreExecute()
{
// TODO Auto-generated method stub
super.onPreExecute();
//showDialog();
Log.d("Now","Inside right now");
dialog = ProgressDialog.show(class_create_event.this, "Loading1", "Please Wait");
}
However the dialog is displayed almost at the end of the request. The I am in part is printed correctly. I know that something is blocking my ui thread. But if I dont call the async task from the UI thread it throws an illegal initializer error. Is there any way out?
You don't need to have UIthread for calling AsyncTask
Call it like this way
FetchRSSFeeds async = new FetchRSSFeeds();
async.execute();
private class FetchRSSFeeds extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog = new ProgressDialog(HomeActivity.this);
/** progress dialog to show user that the backup is processing. */
/** application context. */
protected void onPreExecute() {
this.dialog.setMessage(getResources().getString(
R.string.Loading_String));
this.dialog.show();
}
protected Boolean doInBackground(final String... args) {
try {
// Fetch the RSS Feeds from URL
// do background process
return true;
} catch (Exception e) {
Log.e("tag", "error", e);
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (success) {
// Setting data to list adaptar
setListData();
}
}
}
I would like to do step by step upload date to web service.
My code:
private Thread WebServiceThread;
public void onCreate(Bundle savedInstanceState) {
//...
WebServiceThread = new WebService();
WebServiceThread.start();
}
private class WebService extends Thread {
public void run() {
try {
new WebServiceUpload().execute("");
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT)
.show();
}
}
}
private class WebServiceUpload extends AsyncTask<String, Void, String> {
protected String doInBackground(String... data) {
// upload part
}
protected void onPostExecute(String result) {
//...
WebServiceThread = new WebService();
WebServiceThread.start();
//<Tab>__what to do here__</Tab>
//...
}
}
Now can run, but cause the device slow.
Please tell me how to close parent thread or restart parent thread way to solve this problem. (or other practice to same target.)
You don't have to chain threads like that. Just create a single AsyncTask extension that uploads the data step by step in doInBackground. If you want to publish progress reports, you can do that by calling publishProgress.
Your method of creating a WebServiceUpload from a worker thread is really bizarre and will most likely not work. AsyncTask is designed to be started from the UI thread. Just call your new WebServiceUpload().execute() from the main thread when you want to start the upload steps.
In your onPostExecute check if thread is running then force it to stop.
protected void onPostExecute(String result) {
//...
**if (WebServiceThread.isAlive())
WebServiceThread.stop();**
WebServiceThread = new WebService();
WebServiceThread.start();
//<Tab>__what to do here__</Tab>
//...
}