Accessing UI view in another thread does *not* cause a crash. Why? - android

All:
I really don't grok handlers yet. I thought that the code below -- modified so that, instead of using a handler, the UI widget (progress bar) was accessed directly -- would cause a cross-threading exception. But it doesn't. So, my question is, shouldn't this code crash? And if it doesn't, then when do I need to use a handler?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
progress = 0;
progressBar = (ProgressBar) findViewById(R.id.progressbar);
progressBar.setMax(200);
//---do some work in background thread---
new Thread(new Runnable()
{
public void run()
{
//ó-do some work hereó-
while (progressStatus < 200)
{
progressStatus = doSomeWork();
progressBar.setProgress(progressStatus); // not on UI thread
//ó-Update the progress baró- // so shouldn't it crash?
// handler.post(new Runnable()
// {
// public void run() {
// progressBar.setProgress(progressStatus);
// }
// });
}
//---hides the progress bar---
handler.post(new Runnable()
{
public void run()
{
//---0 - VISIBLE; 4 - INVISIBLE; 8 - GONE---
progressBar.setVisibility(View.GONE);
}
});
}

Nowadays, ProgressBar has logic that allows setProgress() to be called on a background thread. It checks to see what thread you are on and does its own post() of a Runnable if needed. You can see this in the source code.

Related

Updating UI In Android

I want to Update UI from background thread and if user wants to interact with UI while updating then the UI should not blocked by background thread.
Please Help me out.
This can be done using handlers to post UI updates from background thread. You can refer https://developer.android.com/training/multiple-threads/communicate-ui.html for code sample.
Using this you can update UI from backgorund thread
runOnUiThread()
runOnUiThread(new Runnable() {
#Override
public void run() {
//ui update stuff
}
});
You can use handler to serve this purpose.
A simple example:
Create a class:
class Task implements Runnable {
#Override
public void run() {
for (int i = 0; i <= 20; i++) {
final int value = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
progressBar.setProgress(value);
}
});
}
}
}
Then call it from where you want to update the UI like this:
new Thread(new Task()).start();
Complete Example can be found here.
Or you can also go with different approach. Using runOnUiThread method will also allow you to achieve your expected result.
Example:
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setText("#" + i);
}
});

Thread not executing UI comes out saying unfortunately stopped

Where timer is a textview and throws error during runtime and UI comes out saying unfortunately has stopped.Have attached error mess link below.Plz help not understanding where I am going wrong
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.level_twolayout);
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
Timer.setText("Hello");
}
}
});
t1.start();
}
You must update UI from main thread.
Use this code. in place of Timer.setText("Hello");
// verify we are indeed updating UI on main thread.
runOnUiThread(new Runnable() {
#Override
public void run() {
// go ahead and update UI
Timer.setText("Hello");
}
});
runOnUiThread is an Activity method. See http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29.
You need to call MyActivityName.this.runOnUiThread() or more simply just runOnUiThread() as "this" will point to the scope of the Runnable you are creating and not your Activity.
Lastly, "Timer" may not be the best name for your TextView.

Android Horizontal progresBar progress stops in the middle

I'm a "fresh" Android developer and i tried the horizontal ProgressBar.
I have a little issue with it, progress stops in the middle and does not continue till the end of the bar.
Can you help me please?
this is my code
progress=0;
mProgress = (ProgressBar) findViewById(R.id.progressBar1);
mProgress.setMax(200);
// Start lengthy operation in a background thread
new Thread(new Runnable()
{
public void run()
{
while (mProgressStatus < 100)
{
mProgressStatus = doWork();
// Update the progress bar
mHandler.post(new Runnable()
{
public void run()
{
mProgress.incrementProgressBy(20);
mProgress.setProgress(mProgressStatus);
}
});
}
// Cache la progressBar
mHandler.post(new Runnable()
{
#Override
public void run()
{
mProgress.setVisibility(4);
}
});
}
//---------------------------------Work to do-----------------------
private int doWork()
{
try{
Thread.sleep(50);//5 secondes
}catch(InterruptedException e)
{
e.printStackTrace();
}
return ++progress;
}
//------------------------------------------------------------------
}).start();
}
You set the progress bar maximum value to 200:
mProgress.setMax(200);
and later in code you stop when it raises to 100 (half filled). Either set the maximum to 100 or keep running till 200.

ProgressDialog won't dismiss in Thread

I am new to Android dev, and am trying to solve this problem that has been giving me some frustration. I am trying to close this progressDialog. When I run the app, it displays, the information is fetched, and the UI is updated. However, the dialog is never dismissed.
progDialog = ProgressDialog.show(HomeActivity.this, "", "Fetching info...", true, false);
new Thread(new Runnable() {
public void run() {
fetchInfomation(userID); //fetches information - Works
runOnUiThread(new Runnable() {
public void run() {
setLayoutList(); //updates UI - Works
progDialog.dismiss(); //doesn't seem to close progress dialog
firstView(); //displays prompt - Works
}
});
progDialog.dismiss(); //doesn't close dialog either
}
}).start();
Any ideas?
You can't interact with UI inside an external thread. There is some techniques to do that but it's not necessary.
You can use Handler.
For example:
...
private Handler mHandler;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
mHandler = new Handler() {
#Override
public void handleMessage (Message msg) {
switch (msg.what) {
case 0: ...
case 1: ...
}
}
}
}
And:
....
new Thread() {
#Override
public void run() {
... // do your background jobs here
mHandler.sendEmptyMessage(...); // interact with UI
});
}
}.start();
It will be good practice if you do any GUI updates on UI thread. Inside any thread you can run your UI thread where you can do the UI stuffs or else you can go for message handler also which will do the same for you.
Runnable run_in_ui = new Runnable() {
#Override
public void run() {
// do your UI stuffs here
}
};
runOnUiThread(run_in_ui);

ProgressBar update from within Handler

I have a syncing service that I want a progress bar for, because it takes >1 minute to sync all the data and I don't want to use indeterminate progress. I have a Handler for the syncing functions and am referencing and correctly updating the progressBar's progress but the UI does not update.
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
//Sync calls
updateProgress(getContext());
}
};
public static void updateProgress(Context c){
layout = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
progress_view = layout.inflate(R.layout.sync_dialog, null);
mProgressStatus += mProgressStep;
mProgress = (ProgressBar) progress_view.findViewById(R.id.progress);
mProgress.setProgress(mProgressStatus);
}
I have tried using an ASynchTask class with no success. Any help is appreciated.
Let this my example of right use of Handler.
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
bar.incrementProgressBy(5);
if (bar.getProgress() == 100) {
bar.setProgress(0);
Toast.makeText(ThreadsDemoActivity.this, "Progress is finished.", Toast.LENGTH_SHORT).show();
}
}
};
Then you have to create Thread(now it do only some simulation or work)
#Override
public void onStart() {
super.onStart();
bar.setProgress(0);
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
try {
for (int i = 0; i < 20 && isRunning; i++) {
Thread.sleep(300);
handler.sendMessage(handler.obtainMessage());
}
}
catch (Throwable t) {
}
}
});
isRunning = true;
backgroundThread.start();
}
public void onStop() {
super.onStop();
isRunning = false;
}
Also in onCreate method you have to declare and initialise progressBar
bar = (ProgressBar) findViewById(R.id.progBar)
So this is good but not always. More complex approach offers AsyncTask. It's very complex and strong tool and when i would recommend to you something so clearly it's AnyncTask. It's generic type and has one method named doInBackground() that are using for long-time tasks and trasfers your task to background. There is one rule that you cannot update UI from background thread. You cannot but AsyncTask offers onProgressUpdate() method that are using for updating UI. But enough, if you want, have look at AsyncTask.
Regards
you should use Thread or AsyncTask for that,And only handler update progressBar meanwhile you sync all the data.
See this Example and put your sync code in doInBackground method

Categories

Resources