How to add tabbar in doinbackground asynctask in android? or how to run splash screen in thread? I want to show a progress dialog or splash screen until tab bar is loaded from calling tabbar class I am calling webservices and parsing the value takes time, for few mins mean time, I have to show progessbar or splash screen. Can anybody tell me how to implement this? Can anybody give sample code?
I tried but its not working
dlg = ProgressDialog.show(this, "Working..", "Downloading Data...", true, false);
Thread splashThread = new Thread() {
#Override
public void run() {
try {
sleep(100000);
} catch (InterruptedException e) {
// do nothing
} finally {
}
}
};
splashThread.start();
you cannot touch anything of the main ui thread from a background thread, in order to do that you have to use a handler who manages the synchronization between background thread and ui main thread.
the better way is subclassing the AsyncTask, doing this, you already have methods who works on background and methods who work on the ui. With this, you can perform the background operation and inmediatly shows the result...
public class AsynchronousTask extends AsyncTask<Runnable, String, Result> {
//method executed automatically in the ui event before the background thread execution
#Override
protected void onPreExecute() {
//show the splash screen and add a progress bar indeterminate
}
//method executed automatically in the ui event AFTER the background thread execution
#Override
protected void onPostExecute(Result result) {
//hide the splash screen and drop the progress bar or set its visibility to gone.
}
//method executed in a background event when you call explicitly execute...
#Override
protected Result doInBackground(Runnable... tasks) {
Result result;
if(tasks != null && tasks.length > 0){
for (Runnable runnable : tasks) {
//publishProgress( ... );
runnable.run();
//result = ...
//publishProgress( ...);
}
}
return result;
}
}
http://developer.android.com/reference/android/os/AsyncTask.html
read more here
hope this helps...
Related
Edit: It was suggested that it would be helpful to add my code so, my AsyncTask code is now pasted below...
I'm just learning Android and I have a UI with a few buttons. I want to animate the UI, changing the color of the buttons, in a sequence.
I shouldn't do that from the main thread of course, and it doesn't work anyway. The code manipulating the UI runs but the UI doesn't update until the end of the sequence.
So I created a thread and tried to run through the sequence from a background thread however, I would get an error trying to manipulate the UI components from the background thread. Only the main thread can touch the UI components.
Then I discovered AsyncTask. What I figured was, I could run through the sequence in doInBackground(). Every time I needed to update the UI I'd call publishProgress() which would cause onProgressUpdate() to be called from the main thread so I could access UI components without error.
Every time I call publishProgress() I would follow it with a SystemClock.sleep(500) to let time pass until the next animated UI update.
What I found though was that doInBackground() would run through the 4 UI state changes in about 2 seconds (500 ms each) but the UI would not update with each call to publishProgress(). Instead doInBackground() completes and then onProgressUpdate() is called 4 times in a row.
From the description, publishProgress & onProgressUpdate are designed to update a progress bar as doInBackground cranks through some longish running task so, obviously, onProgressUpdate must execute multiple times before doInBackground completes, right?
Am I missing something?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startGame(View view) {
MyTask task = new MyTask();
task.doInBackground();
}
class MyTask extends AsyncTask<Void,Void,Void> {
private int current_int;
#Override
protected Void doInBackground(Void... voids) {
this.current_int = 1;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
this.current_int = 2;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
this.current_int = 1;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
this.current_int = 2;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
return null;
}
#Override
protected void onProgressUpdate(Void... voids) {
super.onProgressUpdate(voids);
Log.e("onProgressUpdate","Updating button "+this.current_int);
Button btn1 = (Button) findViewById(R.id.button1);
Button btn2 = (Button) findViewById(R.id.button2);
if (this.current_int==1){
btn1.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light));
btn2.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark));
} else {
btn2.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light));
btn1.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark));
}
}
}
}
Just for reference : An Asynctask presents a systematic way to transition from main thread (calling thread) to the new thread (called thread). The onPreExecute() and onPostExecute() methods execute on the calling thread and the doInBackground() is the actual method executing on the new thread. Doing UI updates on main thread will hence lead to exception if done from doInBackground() method.
Your core background logic should hence be placed in the doInBackground() method.
If you want to update UI from background thread (Asynctask or otherwise), you can do it using this :
YourActivity.this.runOnUiThread(new Runnable(){
#Override
public void run()
{
//UI update operations here
}
});
You can use Handler for this,
public class TestClass extends AsyncTask<Void,Void,Void> {
boolean isRunning = true; //set false after executing UI logic.
Handler mHandler = new Handler();
#Override
protected Void doInBackground(Void... params) {
YourFunctionToUpdateUI();
return null;
}
public void YourFunctionToUpdateUI()
{
new Thread(new Runnable() {
#Override
public void run() {
while (isRunning) {
try {
mHandler.post(new Runnable() {
#Override
public void run() {
// your code to update the UI.
}
});
} catch (Exception e) {
//handle exception
}
}
}
}).start();
}
}
I'm an idiot. The problem is, I'm creating an AsyncTask and then calling doInBackground() directly, from my main thread instead of calling execute() which creates the background thread
I need to process some data when the user click the button in one activity, so the screen looks like the app stops for 2-3 seconds. It isn't a lot but I want to give the user information that everything is ok and IMO the best way will be the progressbar which is visible only when data are processed.
I found the code of ProgressBar and it looks like this:
<ProgressBar
android:id="#+id/loadingdata_progress"
style="?android:attr/progressBarStyle"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignBottom="#+id/fin2_note"
android:layout_centerHorizontal="true"
android:indeterminate="true"
android:visibility="invisible" />
and inserted it on the middle of my layout.
And to try if the progressbar works, I put this code
loadingimage= (ProgressBar) findViewById(R.id.loadingdata_progress);
loadingimage.setVisibility(View.VISIBLE);
into onCreate method and everything looks fine.
Then I recreated the code to show this progressbar only if the data is processed.
After click the user invoke this method
public void fin2_clickOnFinalization(View v)
{
loadingimage= (ProgressBar) findViewById(R.id.loadingdata_progress);
loadingimage.setVisibility(View.VISIBLE);
// code where data is processing
loadingimage.setVisibility(View.INVISIBLE);
}
and nothing appear on the screen. I don't know where is the mistake. If I found the progress bar by id, It's strange for me that I can control it in onCreate method but in onclick method it's out of my control.
Your UI thread cannot show progress bar cause it is busy due to your data processing. Try to use this kind of code :
public void fin2_clickOnFinalization(View v) {
new YourAsyncTask().execute();
}
private class YourAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... args) {
// code where data is processing
return null;
}
#Override
protected void onPostExecute(Void result) {
loadingimage.setVisibility(View.INVISIBLE);
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
loadingimage.setVisibility(View.VISIBLE);
}
}
EDIT:
AsyncTask let you run code in separate thread and make app more responsive, just put time-consuming code inside doInBackground.
You're not giving the UI time to refresh. Your "data processing" code is running on the UI thread, blocking any visible changes. By the time the system gets control to refresh the display, you've already set it back to invisible.
To fix this, move your processing code to a separate thread or AsyncTask. Then you can set the progress bar to visible, start the task, and have it turn itself invisible once it's done.
I'd recommend AsyncTask for this purpose about 90% of the time on Android, since it comes stock with useful callbacks. The developer guide for it(in the Javadoc linked above) is pretty explicit, and outlines all the steps you need to take.
AsyncTask is too heavily-weighted for such task.
A better much solution
Handler handler = new Handler(getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
loadingimage.setVisibility(View.VISIBLE);
}
});
Or even simpler (does essentially the same thing as solution above)
runOnUiThread(new Runnable() {
#Override
public void run() {
loadingimage.setVisibility(View.VISIBLE);
}
});
You can try to create a global ProgressDialog not in the layout but in your activity like:
public class MyActivity {
ProgressDialog progress = null;
protected void onCreate(...) {
progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
progressDialog.setTitle("Progress");
}
public void fin2_clickOnFinalization(View v)
{
progress.show();
// code where data is processing
progress.dismiss();
}
}
Hope i it helps
I have a Button, and upon pressing it, the onClick() would process user's request. However, this takes a little time, so I would like to have a View showing "Please wait, processing..." immediately upon pressing this Button, while its OnClickListener does its thing.
My problem is, this "Please wait, processing..." which I placed at the very beginning of onClick(), only appears AFTER the whole onClick() is done. In other words, after the whole processing is done. So, I was wondering, how do I make a View saying "Please wait, processing..." before the actual processing has begun?
As #Blundell pointed you may process long-running operation on a separate thread to avoid freezing of UI thread. However in Android there's a better alternative for general-purpose Handler which is called AsyncTask. Please refer to this tutorial for details.
You can do this by just using AsyncTask without dealing anything else.
First create new AsyncTask class on "onPreExecute" change ui to show
that you are processing sth
Second do your all backend time consuming job on "doInBackground"
method (do not call any ui updating method from here)
Third change your ui to show that process is finished or whatever you
wanna do.
yourUiButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
new NewTask().execute();
}
});
class NewTask extends AsyncTask<String, Void, Task>{
#Override
protected void onPreExecute() {
super.onPreExecute();
//this part runs on ui thread
//show your "wait while processing" view
}
#Override
protected Task doInBackground(String... arg0) {
//do your processing job here
//this part is not running on ui thread
return task;
}
#Override
protected void onPostExecute(Task result) {
super.onPostExecute(result);
//this part runs on ui thread
//run after your long process finished
//do whatever you want here like updating ui components
}}
Do the processing on another thread so that the UI can show your dialog.
// Show dialog
// Start a new thread , either like this or with an ASyncTask
new Thread(){
public void run(){
// Do your thang
// inform the UI thread you've finished
handler.sendEmptyMessage();
}
}
When the processing is done you will need to callback to the UI thread to dismiss oyur dialog.
Handler handler = new Handler(){
public void handleMessage(int what){
// dismiss your dialog
}
};
AsyncTasks.
Place the displaying of the progress dialog in onPreExecute
Do your thing in doInBackground
Update whatever needs to be updated in the UI, and close the dialog in onPostExecute
You will need something like this
public void onClick(View v){
//show message "Please wait, processing..."
Thread temp = new Thread(){
#Override
public void run(){
//Do everything you need
}
};
temp.start();
}
or if you want it to run in the UIThread (since it is an intensive task, I don't recommend this)
public void onClick(View v){
//show message "Please wait, processing..."
Runnable action = new Runnable(){
#Override
public void run(){
//Do everything you need
}
};
v.post(action);
}
put ur code inside a thread and use a progress dialogue there...
void fn_longprocess() {
m_ProgressDialog = ProgressDialog.show(this, " Please wait", "..", true);
fn_thread = new Runnable() {
#Override
public void run() {
try {
// do your long process here
runOnUiThread(UI_Thread);//call your ui thread here
}catch (Exception e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(null, thread1
"thread1");
thread.start();
}
then close your dialogue in the UI thread...hope it helps..
I've developed an application that takes content from the internet and shows it accordingly on the device's screen . The program works just fine , a little bit slow . It takes about 3-4 seconds to load and display the content . I would like to put all the code that fetches the content and displays it in a background thread and while the program is doing those functions , I would like to display a progress dialog. Could you help me do this ? I would like especially to learn how to put the code in a background thread.
MY CODE
public class Activity1 extends Activity
{
private ProgressDialog progressDialog;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new AsyncTask<Integer, Integer, Boolean>()
{
ProgressDialog progressDialog;
#Override
protected void onPreExecute()
{
/*
* This is executed on UI thread before doInBackground(). It is
* the perfect place to show the progress dialog.
*/
progressDialog = ProgressDialog.show(Activity1.this, "",
"Loading...");
}
#Override
protected Boolean doInBackground(Integer... params)
{
if (params == null)
{
return false;
}
try
{
/*
* This is run on a background thread, so we can sleep here
* or do whatever we want without blocking UI thread. A more
* advanced use would download chunks of fixed size and call
* publishProgress();
*/
Thread.sleep(params[0]);
// HERE I'VE PUT ALL THE FUNCTIONS THAT WORK FOR ME
}
catch (Exception e)
{
Log.e("tag", e.getMessage());
/*
* The task failed
*/
return false;
}
/*
* The task succeeded
*/
return true;
}
#Override
protected void onPostExecute(Boolean result)
{
progressDialog.dismiss();
/*
* Update here your view objects with content from download. It
* is save to dismiss dialogs, update views, etc., since we are
* working on UI thread.
*/
AlertDialog.Builder b = new AlertDialog.Builder(Activity1.this);
b.setTitle(android.R.string.dialog_alert_title);
if (result)
{
b.setMessage("Download succeeded");
}
else
{
b.setMessage("Download failed");
}
b.setPositiveButton(getString(android.R.string.ok),
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dlg, int arg1)
{
dlg.dismiss();
}
});
b.create().show();
}
}.execute(2000);
new Thread()
{
#Override
public void run()
{
// dismiss the progressdialog
progressDialog.dismiss();
}
}.start();
}
}
The app crashes , NullPointerException among other stuff . Could you help me ? thanks.
You code is fine, except for the last Thread, which, beside being useless, is the reason your app crashes : when the thread is started, the progressDialog is not initialized yet.
Otherwise, this should work like a charm.
Edit
One more thing: giving null as a onClickListener for the positive or negative button simply dismiss the dialog (which is what you do), so
b.setPositiveButton(android.R.string.ok, null);
is equivalent, only shorter.
You do the downloading in the doInBackground() method. Now you need to override onProgressUpdate() method where you'll do .setProgress() to your progressbar. onProgressUpdate() runs on ui-thread. Use .publishProgress() method from where (from background thread i.e doInBackground() method) you'll make a call to onProgressUpdate().
I hope this idea will help you.
http://developer.android.com/reference/android/os/AsyncTask.html#publishProgress(Progress...)
I have a problem with progress dialog on opening an activity (called activity 2 in example).
The activity 2 has a lot of code to execute in this OnCreate event.
final ProgressDialog myProgressDialog = ProgressDialog.show(MyApp.this,getString(R.string.lstAppWait), getString(R.string.lstAppLoading), true);
new Thread() {
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
showApps();
}
});
myProgressDialog.dismiss();
}
}.start();
The showApps function launch activity 2.
If I execute this code on my button click event on activity 1, I see the progress, but she doesn't move and afeter I have a black screen during 2 or 3 seconds the time for android to show the activity.
If I execute this code in the OnCreate of Activity2 and if I replace the showApps by the code on OnCreate, Activity1 freeze 2 seconds, I don't see the progress dialog, and freeze again 2 seconds on activity 2 before seeing the result.
I had the same issue and using an AsyncTask is working for me.
There are 3 important methods to override in AsyncTask.
doInBackground : this is where the meat of your background
processing will occur.
onPreExecute : show your ProgressDialog here ( showDialog )
onPostExecute : hide your ProgressDialog here ( removeDialog or dismissDialog
)
If you make your AsyncTask subclass as an inner class of your activity, then you can call the framework methods showDialog, dismissDialog, and removeDialog from within your AsyncActivity.
Here's a sample implementation of AsyncTask:
class LoginProgressTask extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
try {
Thread.sleep(4000); // Do your real work here
} catch (InterruptedException e) {
e.printStackTrace();
}
return Boolean.TRUE; // Return your real result here
}
#Override
protected void onPreExecute() {
showDialog(AUTHORIZING_DIALOG);
}
#Override
protected void onPostExecute(Boolean result) {
// result is the value returned from doInBackground
removeDialog(AUTHORIZING_DIALOG);
Intent i = new Intent(HelloAndroid.this, LandingActivity.class);
startActivity(i);
}
}
AFAIK you cannot preload any activity with progress dialog displayed. Are you testing on a real device or in emulator?
I've seen workarounds that opened an activity with a ViewFlipper having a progress animation in the center, and in the next View, it was loaded an activity, but it's not something is recommended and hard to implement to work as you wish.
GeeXor
I would suggest you to avoid performing lots of operations in Activity 2's OnCreate.Writing lots of operations in OnCreate is a reason for the black screen between activities.So perform those operations asynchronously using AsyncTask or in a Thread (or write them in onStart if they are unavoidable).
The other suggestion is to start another progressDialog in activity 2's onCreate which will run until all of your data is loaded & user will know that something is happening in background.
this is what i would do. create a handler on the ui thread, start the background processing thread and then show the progressdialog. when the background thread has finished it's work get it to post a runnable on the ui thread via the handler to dismiss the dialog.