I have a simple function that shows loading spinner while fetching data (usually takes 7 seconds or so)
private void load_data(View v)
{
task_complete = false;
progressBar = new ProgressDialog(v.getContext());
progressBar.setCancelable(false);
progressBar.setMessage("Fetching data ...");
progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressBar.show();
try
{
Log.v("thread", "Starting thread");
new Thread(new Runnable()
{
public void run()
{
while(!task_complete)
{
fetch_data();
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
progressBar.dismiss();
}
}).start();
Log.v("thread", "Thread finished successfully");
}
catch(Exception e)
{
Log.v("thread", "fail "+e.toString());
}
}
The problem I have is that the function gets called by onClick via
load.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
load_data(v);
show_data(v); // shows the data on a spinner
}
});
And when I press the load button the second time I get an error. My log does show
Starting thread
Thread finished successfully
But somehow the app dies with an error saying
03-27 02:48:39.282: E/AndroidRuntime(956): Uncaught handler: thread Thread-9 exiting due to uncaught exception
03-27 02:48:39.293: E/AndroidRuntime(956): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
03-27 02:48:39.293: E/AndroidRuntime(956): at android.view.ViewRoot.checkThread(ViewRoot.java:2683)
I would greatly appreciate it if someone can show me or explain to me what causes the error
The problem is that your progressBar.dismiss(); is executed in another thread, to make it run in UI thread, do this:
runOnUiThread(new Runnable() {
#Override
public void run() {
progressBar.dismiss();
}
});
ProgressDialog is a View and you can access it in the UI thread (or main thread) only. Use AsyncTask instead of threads.
EDIT
This official link will help you get the hang of AsyncTask. The thing to remember is doInBackground() method runs in separate thread where you should put your data loading method i.e. fetch_data(). Once the method completed execution, onPostExecute() will get called, which will run on UI thread, where you can dismiss the dialog. You can start the dialog in the onPreExecute() method.
Though in this context you do not need the onProgressUpdate() method, but just FYI, it is used to update the Views in UI thread while the loading is still working using publishProgress() call (In case you use the AsyncTask in future).
PS: Only the doInBackground() method runs in separate thread, every other method runs in UI thread. The rule about not accessing the View in any other thread except the UI one, still applies here.
Related
06-06 23:50:28.340 27670-27706/mys.timer E/AndroidRuntime: FATAL EXCEPTION: Timer-0
Process: mys.timer, PID: 27660
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
My code:
protected void onCreate(Bundle savedInstanceState) {
public void run() {
new Timer().scheduleAtFixedRate(new TimerTask(){
#Override
public void run(){
status.setText(getResources().getString(R.string.timercount));
status.setTextColor(Color.parseColor("#990000"));
}
}
}
Please tell me how can i avoid my app from closing itself
Android’s UI components are not thread safe so one may need to update Views or other UI components from a secondary thread when returning from an asynchronous database query or a web service call. If you run the code from a secondary thread you might see that the code crashes almost on each try.
runOnUIThread Activity’s method
yourActivity.runOnUiThread(new Runnable(){
public void run() {
// UI code goes here
}
});
I hope that it helps you.
I have following code to run a function in another thread:
Button buttonb = (Button) this.findViewById(R.id.buttonb);
buttonb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
…
progressBar.setVisibility(View.VISIBLE);
Thread thread = new Thread() {
#Override
public void run() {
matrixOperation(sourcePhoto);
}
};
thread.start();
progressBar.setVisibility(View.INVISIBLE);
…
}
});
But on running i am getting this error:
Can't create handler inside thread that has not called Looper.prepare()
I searched and found that one reason for this error is “You cannot execute an AsyncTask from a background thread. See the "Threading Rules" section of” But this is not background thread I am calling it from my Main Activity.
Please tell me how I can fix this.
The Handler class uses Loopers to perform its scheduling, and threads that have just been created does not have an associated looper – hence the error.
As you have not provided the handler creation code, I'm assuming you want to call code on the main thread. In this case, create the Handler as follows:
Handler handler = new Handler(Looper.getMainLooper());
Anything scheduled to run on that Handler will execute on the main Looper, which is running on the main thread.
I am following this tutorial to have a loading screen in my program. The tutorial says my activity should Sleep() using the Sleep() command, however it does not recognize Sleep() as a function and provides me with an error, asking if I would like to create a method called Sleep().
Here is the code sample:
public class LoadingScreenActivity extends Activity {
//Introduce an delay
private final int WAIT_TIME = 2500;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
System.out.println("LoadingScreenActivity screen started");
setContentView(R.layout.loading_screen);
findViewById(R.id.mainSpinner1).setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
//Simulating a long running task
this.Sleep(1000);
System.out.println("Going to Profile Data");
/* Create an Intent that will start the ProfileData-Activity. */
Intent mainIntent = new Intent(LoadingScreenActivity.this,ProfileData.class);
LoadingScreenActivity.this.startActivity(mainIntent);
LoadingScreenActivity.this.finish();
}
}, WAIT_TIME);
}
}
You can use one of the folllowing methods:
Thread.sleep(timeInMills);
or
SystemClock.sleep(timeInMills);
SystemClock.sleep(milliseconds) is a utility function very similar to Thread.sleep(milliseconds), but it ignores InterruptedException. Use this function for delays if you do not use Thread.interrupt(), as it will preserve the interrupted state of the thread.
The function is Thread.sleep(long).
Note, however, that you should not perform a sleep on the UI thread.
The code you posted is horrible. Please don't use that on an actual device. You will get an "Application Not Responding" error if you run something similar to this.
If you're using Handlers, keep in mind that a Handler is created on the thread where it runs. So calling new Handler().post(... on the UI thread will execute the runnable on the UI thread, including this "long running operation". The advantage is that you can create a Handler to the UI Thread which you can use later, as shown below.
To put the long running operation into a background thread, you need to create a Thread around the runnable, as shown below. Now if you want to update the UI once the long running operation is complete, you need to post that to the UI Thread, using a Handler.
Note that this functionality is a perfect fit for an AsyncTask which will make this look a lot cleaner than the pattern below. However, I included this to show how Handlers, Threads and Runnables relate.
public class LoadingScreenActivity extends Activity {
//Introduce a delay
private final int WAIT_TIME = 2500;
private Handler uiHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
uiHandler = new Handler(); // anything posted to this handler will run on the UI Thread
System.out.println("LoadingScreenActivity screen started");
setContentView(R.layout.loading_screen);
findViewById(R.id.mainSpinner1).setVisibility(View.VISIBLE);
Runnable onUi = new Runnable() {
#Override
public void run() {
// this will run on the main UI thread
Intent mainIntent = new Intent(LoadingScreenActivity.this,ProfileData.class);
LoadingScreenActivity.this.startActivity(mainIntent);
LoadingScreenActivity.this.finish();
}
};
Runnable background = new Runnable() {
#Override
public void run() {
// This is the delay
Thread.Sleep( WAIT_TIME );
// This will run on a background thread
//Simulating a long running task
Thread.Sleep(1000);
System.out.println("Going to Profile Data");
uiHandler.post( onUi );
}
};
new Thread( background ).start();
}
use Thread.sleep(1000);
1000 is the number of milliseconds that the program will pause.
try
{
Thread.sleep(1000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
Keep in mind: Using this code is not recommended, because it is a delay of time but without control and may need more or less time.
I'm working on an app that connect to a webpage to get some content. I want to show a progressdialog, but I think I'm doing something wrong.
This is my code:
final ProgressDialog myProgressDialog = ProgressDialog.show(WhoisBeyondActivity.this, "Wait...", "Fetching data...", true);
Handler handler=new Handler();
handler.post(new Runnable()
{
public void run()
{
try {
// code to execute
Thread.sleep(2000);
} catch (Exception e) {
}
myProgressDialog.dismiss();
}
});
The problem is that the progressdialog is only shown one second at the end of the operation I want to make. I think the progressdialog is only executing when I execute the dismiss() because it appears and dissapears quickly. Is like the progressdialog appears only to dissapear ... help me please!!! I have read a lot of tutorials, and I have try a lot of option, like THREAD instead of HANDLER, but it is not usefull for me, because I have to edit UI.
There's an excellent example and tutorial here:
http://www.helloandroid.com/tutorials/using-threads-and-progressdialog
That's what I used the first time I did a threaded dialog in Android, and I bookmarked it. Hopefully it helps.
The reason you are getting the described behaviour is that the post method will just execute the passed in runnable against the thread to which the Handler is attached. In your case this is the UI thread.
You are calling ProgressDialog.show(), which is asynchronous. This does not actually show the dialog as soon as the method returns, rather you have just requested that the UI display a dialog. You then immediately post a thread that sleeps for 2 seconds, which is added to the UI queue and blocks the UI from performing the dialog show. The UI then wakes from your sleep, shows the dialog then is dismissed.
You should perform any network operation in either a new Thread or in an AsyncTask. Have a look at these links for more details:
AsyncTask
Painless threading
Threading
Designing for responsiveness
Thread documentation
Handler documentation
You don't want to use a separate thread per-say. What you really want is an AsynTask. This will allow you to create the progress dialog and do the background processing right there in the task. Simple to write and easier to implement. If your refer to the link, what you need is actually really similar to your question. With a little tweaking, it should work just fine for you.
public class HelloActivity extends Activity {
protected static final String TAG = "HelloActivity";
ProgressDialog myProgressDialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//
showDialog(1);
final Handler handler=new Handler(){
#Override
public void handleMessage(Message msg) {
//update UI here depending on what message is received.
switch(msg.what){
case 0:
myProgressDialog.dismiss();
}
super.handleMessage(msg);
}
};
Thread t = new Thread(){
public void run(){
try {
// code to execute
Thread.sleep(5000);
} catch (Exception e) {
}
handler.sendEmptyMessage(0);//nothing to send
}
};
t.start();
}
#Override
protected Dialog onCreateDialog(int id) {
myProgressDialog = ProgressDialog.show(HelloActivity.this, "Wait...", "Fetching data...", true);
return myProgressDialog;
}
}
I am trying to create a simple exception handler which will help me debug the application. Right now, when I have an exception I am forced to connect with Eclipse debugger merely to see the exception details.
To avoid that I've used setUncaughtExceptionHandler to handle any unhandled exception and display a Toast on the exception. Unfortunately, that doesn't work.
public class TicTacToe extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
Toast.makeText(TicTacToe.this, "TOAST", Toast.LENGTH_LONG).show();
}
});
setContentView(R.layout.main);
Button continueButton = (Button) findViewById(R.id.cell01);
continueButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int i = 5;
i = 5 / 0;
Toast.makeText(TicTacToe.this, "BUTTON", Toast.LENGTH_LONG).show();
}
});
}
}
Essentially I made a form with a single button, pressing on which, it would throw a devision-by-zero exception. However, pressing the button doesn't cause the global toast handler to show. Instead, the button stays orange (pressed) and nothing happens.
Needless to say, if I comment out i = 5 / 0; I see the toast that says that a button was pressed.
Two questions:
1) Why isn't the toast showing in the UncaughtExceptionHandler body? How do cause it to show?
2) Is there an alternative/better way for global exception handling? I guess I could install aLogCat on the android simulator and simply log the uncaught exception, it seems, however, less comfortable - I will need to be switching applications just to see exception details.
Thanks!
It is possible. You need to do it inside another thread
Then it should be like this
Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
new Thread() {
#Override
public void run() {
Looper.prepare();
Toast.makeText(TicTacToe.this, "TOAST", toast.LENGTH_LONG).show();
Looper.loop();
}
}.start();
}
});
You're not seeing anything because the exception happened on your UI thread and the stack unrolled all the way. So there is no more Looper and there is no support there that is used to display the Toast. If you want to display the exception information on screen you'll most likely need to start another Activity in another process.
There is also a problem with your UncaughtExceptionHandler. You really should keep a reference to the old one and call it at the end of uncaughtException this allows the system to display the Force Close button.
I know it's an old question but I hope I can save someone from frustration and wasting time.
Qberticus is right, you can't start an Activity on the same process, but you can kill the current process and have android run it in a new one:
Intent intent = new Intent(myContext, AnotherActivity.class);
intent.putExtra("error", errorReport.toString());
myContext.startActivity(intent);
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(10);
refer to this page for an awesome working example: