Whenever I change the orientation, there is an error with the thread and my application closes unexpectedly.
Here is the error code
03-23 11:25:40.021: W/dalvikvm(27571): threadid=14: thread exiting with uncaught exception (group=0x40cecae0)
03-23 11:25:40.021: E/AndroidRuntime(27571): FATAL EXCEPTION: Thread-11869
03-23 11:25:40.021: E/AndroidRuntime(27571): java.lang.NullPointerException
03-23 11:25:40.021: E/AndroidRuntime(27571): at my.app.Methods$1.run(Methods.java:34)
Here is the code for the thread :
SettingsPreferences mSettingsPreferences = new SettingsPreferences(mContext);
public void loadStatistic (final ProgressBar progBar, final SettingsPreferences settPref, final String max, final String progress, final int defaultValue) {
Thread t = new Thread () {
public void run() {
try {
sleep(100);
progBar.setMax(settPref.getInt(max, defaultValue));
progBar.setProgress(settPref.getInt(progress, defaultValue));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t.start();
}
This is because you are trying to acccess the UI on a seperate thread. You will need to use an AsyncTask thread which will enable you to periodically access the UI thread.
For example:
private class ExampleThread extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {}
#Override
protected void doInBackground(Void... params) {
while(!isCancelled()) { // Keep going until cancelled
try {
Thread.sleep(100); // Delay 100 milliseconds
} catch (InterruptedException e) {
Thread.interrupted();
}
publishProgress(); // Run onProgressUpdate() method
if(isCancelled()) break; // Escape early if cancel() is called
}
}
#Override
protected void onPostExecute(Void... params) {}
#Override
protected void onProgressUpdate(Void... params) {
// Here you can access the UI thread
progBar.setMax(settPref.getInt(max, defaultValue));
progBar.setProgress(settPref.getInt(progress, defaultValue));
}
}
To start the thread:
ExampleThread thread = new ExampleThread();
thread.execute();
To stop the thread:
thread.cancel();
More information and examples with AsyncTask can be found on this question.
You must update all of your UI elements on the main or UI thread. I would recommend creating an AsyncTask subclass and then implementing onPreExecute and onPostExecute to start and stop the progress bar or to measure times. Then do all of your UI things on runOnUiThread .
runOnUiThread takes a Runnable as an argument so you can do everything your heart desires
Related
In my application, there are multiple asynctasks. Please let me know why doInBackground of an asynctask sometimes does not getting called. Its onPreExecute method gets called. Is there any issue because of multiple asynctasks or something else?
/* ASync class for test table */
public class TestAsynch extends AsyncTask<String, Void, String>{
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
String result1=API_Manager.getInstance().sendTestData(userName);
try {
if(result1 != null) {
// save in db
}
}
}
catch( Exception e) {
e.printStackTrace();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
If your project has multiple asynctasks you must check that there is a limit of asynctasks that can be executed. When you create a new AsyncTask it will be added on a Pool and will be execute only when is possible.
Check this answer:
Multitasking on android
And the docs: ThreadPoolExecutor
Here is an example on how properly handle multiple AsyncTasks AsyncTaskManager
OnPreExecute() gets called on the UI thread and doInBackground() is called on the background thread.
There is one dedicated background thread for the async task. This behaviour can be changed if you want to.
http://android-er.blogspot.in/2014/04/run-multi-asynctask-as-same-time.html
Now, say you have multiple instances of async task and I'm assuming you are calling execute() to run the async tasks. This will trigger all the preExecute immediately since UI thread is free but for the doInBackground it will triggered one by one. Hence it may take some time for the next async task to start.
doInBackground should run on a loop using a Boolean to check before execution. Before your Task is being executed, set a global boolean (may be true/false) depends on which you prefer and values add on thread should call runOnUiThread.
startExect = true;
new TestAsynch().execute();
then change this
public class TestAsynch extends AsyncTask<String, Void, String>{
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
String result1=API_Manager.getInstance().sendTestData(userName);
try {
if(result1 != null) {
// save in db
}
}
}
catch( Exception e) {
e.printStackTrace();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
to this
public class TestAsynch extends AsyncTask<String, Void, String> {
String result1 = null;
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String status = null;
result1=API_Manager.getInstance().sendTestData(userName);
while (startExecute) {
Thread exe = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(5);
}
catch( Exception e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
if(result1 != null) {
// save in db
}
}
});
}
}); exe.start();
}
return status;
}
#Override
protected void onPostExecute(String status) {
}
}
Why does my AsyncTask block the UI Thread?
My application becomes unresponsive while the AsyncTask is taking place.
This is called in the UI Thread:
new AsyncFetch().execute();
This is my AsyncTask class:
class AsyncFetch extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... args) {
String data = null;
try {
data = DataHandler.httpFetch(DataHandler.API_URL);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return data;
}
protected void onPostExecute(String data) {
DataHandler.AsyncFetchResult(data);
}
}
onPostExecute runs on the UI thread. Avoid doing too much work here. Do the heavy stuff in doInBackground and then just update the UI (or whatever you need to do) in onPostExecute.
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>
//...
}
I have a method like:
void doStuffs() {
new asyncCall1().execute();
new asyncCall2().execute();
}
How can I call another method after the two async calls have ended?
Use the get method to wait for the work to complete in a third async task:
(new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
asyncCall1.execute((Void)null);
asyncCall2.execute((Void)null);
try {
asyncCall1.get();
asyncCall2.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return (Void)null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}).execute((Void)null);
You need to invoke the method from the AsyncTask. The easiest way would be to wrap the statement in a public static method within your activity. Otherwise, you can pass the AsyncTask a reference to the activity. The classiest way to do it would be to use a Handler
Either way, your AsyncTask should go
#Override
onPostExecute(Result r)
{
//logic goes here
}
Maybe pass a Handler in to both the AsyncTasks which get called onPostExecute and build logic in to the handler :
Handler asyncTaskHandler = new Handler() {
private boolean firstTaskComplete = false;
#Override
public void handleMessage(Message msg) {
synchronized (firstTaskComplete ) {
if(!firstTaskComplete) {
firstTaskComplete = true;
} else {
// call some other code
}
}
}
};