I want to show the progress dialog while loading the images in grid view.
The problem i'm facing was the current thread and Progress Dialog thread running simultaniously.
public String Method1(){
String output="";
final ProgressDialog aProgDialogL = ProgressDialog.show(this, "", "Loading...");
Thread thread = new Thread() {
public void run () {
//My codes
aHandlerL.post(new Runnable() {
#Override
public void run() {
//Post Runnable codes
aProgDialogL.dismiss();
}
});
}
};
thread.start();
/*
*
*
* OTHER CODES
*
*
*/
return output;
}
In the above example I need to run the code inside Progress Dialog Thread. After it finish executing i need to run my "OTHER CODES". How to do it?
.
I tried using Async task. Before async task completes method1 gets extcuted and reurning the string.
public String Method1(){
String result="";
new GetImages().execute();
return result;
}
public class GetData extends AsyncTask<Void, Void, Integer>{
#Override
protected void onPreExecute() {
aProgDialogL = ProgressDialog.show(Main.this, "", "Loading...");
}
#Override
protected Integer doInBackground(Void... params) {
//Progress Dialig Code
return null;
}
#Override
protected void onPostExecute(Integer result) {
aProgDialogL.dismiss();
//OTHER CODES
super.onPostExecute(result);
}
}
You can use Async task. http://developer.android.com/reference/android/os/AsyncTask.html. There is a good tutorial here. http://www.vogella.com/articles/AndroidPerformance/article.html.Also have a look at this link
http://developer.android.com/guide/components/processes-and-threads.html. Use asynctask modify it according to your needs.
doInBackground()- For long running operations. Don't update ui here.
onPreExecute()- update ui before running the operatio nin background.
onPostExecute()- update ui after running the operation.
I would suggest you to take somewhat different approach.
Dont involve any threads in Method1() function.Rather your Method1() function should be run under separate thread.
Below snippet will help you.
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((Button) findViewById(R.id.btnPopup))
.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
new Thread() {
public void run() {
String answer = Method1();
runOnUiThread(new Runnable() {
#Override
public void run() {
// Here you will write the code which is
// to be executed on main thread.
}
});
};
}.start();
}
});
}
public String Method1() {
// Write code
return "result";
}
}
Instead of that : What about use Timer After specific Time Stop Your thread and and write your code you want after stop statement Like that :
Timer timer=new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
thread.stop;
// Other code }
}, Time You want );
Related
I have designed an app that gets the network information and updates the UI every 5 seconds.
It is advised to do the background processes on a separate thread than the UI thread, and I did so...but I still get an error that:
"I/Choreographer﹕ Skipped 3730 frames! The application may be doing
too much work on its main thread."
Why is that?
Here's my code
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wifiTextView = (TextView)findViewById(R.id.wifi_textView);
ipTextView = (TextView)findViewById(R.id.ip_val_textView);
// and so on
//Updating the UI every mInterval seconds, using a separate thread than UI thread
Thread backgroundThread = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(mInterval);
runOnUiThread(new Runnable() {
#Override
public void run() {
//Log.d(DEBUG_TAG, "run(): Background thread");
MyNetwork network = new MyNetwork(getApplicationContext()); // passing the context
updateUI(network);
}
});
}
} catch (InterruptedException e) {
wifiTextView.setText("Exception: Please Close and Restart the App");
}
}
};
backgroundThread.start();
}
In the same MainActivity class, I have this private function:
private void updateUI(MyNetwork network){
// Handles updating the textviews in the UI
//Log.d(DEBUG_TAG, "updateUI(DeepstreamNetwork)");
if (network.isConnected()){
wifiTextView.setText(R.string.wifi_is_on);
wifiTextView.setTextColor(Color.GREEN);
ipTextView.setText(network.getIpAddress());
else {
wifiTextView.setText(R.string.wifi_is_off);
wifiTextView.setTextColor(Color.RED);
ipTextView.setText("N/A");
}
}
UPDATE
So, I have updated my MainActivity class to have this MyAsyncTask method to handle background work...here's my code:
private class MyAsyncTask extends AsyncTask<Void, Void, MyNetwork> {
#Override
protected void onPostExecute(MyNetwork network) {
updateUI(network);
}
#Override
protected MyNetwork doInBackground(Void... params) {
MyNetwork network = new MyNetwork(getApplicationContext()); // passing the context
return network;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
Two issues:
1) how do I force it to do this background task every 5 seconds. Since the network status changes every few secs (disconnection etc...), so I want it to update the UI respectively.
2) should I call it like this in MainActivity: new MyAsyncTask().execute();
Thanks all
I dont know why you called it Thread backgroundThread = new Thread() because runOnUiThread() is really the main Thread.
You should try this in an asynctask where you only update the UI in onPostExecute()
EDIT:
private class MyAsyncTask extends AsyncTask<Void, Void, String> {
private MyNetwork network;
#Override
protected void onPreExecute() {
this.network = new MyNetwork(getApplicationContext());
}
#Override
protected String doInBackground(Void... params) {
return network.getIpAddress();
}
#Override
protected void onPostExecute(String ipAddress) {
if (this.network.isConnected()){
wifiTextView.setText(R.string.wifi_is_on);
wifiTextView.setTextColor(Color.GREEN);
ipTextView.setText(ipAddress);
else {
wifiTextView.setText(R.string.wifi_is_off);
wifiTextView.setTextColor(Color.RED);
ipTextView.setText("N/A");
}
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
I'm trying to use the UI-Thread, so I've written a simple test activity. But I think I've misunderstood something, because on clicking the button - the app does not respond anymore
public class TestActivity extends Activity {
Button btn;
int i = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
runThread();
}
});
}
private void runThread(){
runOnUiThread (new Thread(new Runnable() {
public void run() {
while(i++ < 1000){
btn.setText("#"+i);
try {
Thread.sleep(300);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}));
}
}
Below is corrected Snippet of runThread Function.
private void runThread() {
new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
btn.setText("#" + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
Just wrap it as a function, then call this function from your background thread.
public void debugMsg(String msg) {
final String str = msg;
runOnUiThread(new Runnable() {
#Override
public void run() {
mInfo.setText(str);
}
});
}
You have it back-to-front. Your button click results in a call to runOnUiThread(), but this isn't needed, since the click handler is already running on the UI thread. Then, your code in runOnUiThread() is launching a new background thread, where you try to do UI operations, which then fail.
Instead, just launch the background thread directly from your click handler. Then, wrap the calls to btn.setText() inside a call to runOnUiThread().
runOnUiThread(new Runnable() {
public void run() {
//Do something on UiThread
}
});
There are several techniques using of runOnUiThread(), lets see all
This is my main thread (UI thread) called AndroidBasicThreadActivity and I'm going to update it from a worker thread in various ways -
public class AndroidBasicThreadActivity extends AppCompatActivity
{
public static TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_basic_thread);
textView = (TextView) findViewById(R.id.textview);
MyAndroidThread myTask = new MyAndroidThread(AndroidBasicThreadActivity.this);
Thread t1 = new Thread(myTask, "Bajrang");
t1.start();
}
}
1.) By passing Activity's instance as an argument on worker thread
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
#Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
activity.runOnUiThread(new Runnable()
{
#Override
public void run()
{
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
2.) By using View's post(Runnable runnable) method in worker thread
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
#Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
AndroidBasicThreadActivity.textView.post(new Runnable()
{
#Override
public void run()
{
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
3.) By using Handler class from android.os package
If we don't have the context (this/ getApplicationContext()) or Activity's instance (AndroidBasicThreadActivity.this) then we have to use Handler class as below -
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
#Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
If using in fragment then simply write
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
// Do something on UiThread
}
});
We use Worker Thread to make Apps smoother and avoid ANR's. We may need to update UI after the heavy process in worker Tread.
The UI can only be updated from UI Thread. In such cases, we use Handler or runOnUiThread both have a Runnable run method that executes in UI Thread.
The onClick method runs in UI thread so don't need to use runOnUiThread here.
Using Kotlin
While in Activity,
this.runOnUiThread {
// Do stuff
}
From Fragment,
activity?.runOnUiThread {
// Do stuff
}
Using Java,
this.runOnUiThread(new Runnable() {
void run() {
// Do stuff
}
});
For fragment use that:
requireActivity().runOnUiThread(() -> {
//your code logic
});
For activity use that:
runOnUiThread(() -> {
//your code logic
});
runOnUiThread is used in a way the UI can be updated with our background thread. For more: https://www.tutorialspoint.com/how-do-we-use-runonuithread-in-android
thy this:
#UiThread
public void logMsg(final String msg) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
}
You can use from this sample :
In the following example, we are going to use this facility to publish the result from a
synonym search that was processed by a background thread.
To accomplish the goal during the OnCreate activity callback, we will set up
onClickListener to run searchTask on a created thread.
When the user clicks on the Search button, we will create a Runnable anonymous
class that searches for the word typed in R.id.wordEt EditText and starts the
thread to execute Runnable.
When the search completes, we will create an instance of Runnable SetSynonymResult
to publish the result back on the synonym TextView over the UI thread.
This technique is sometime not the most convenient one, especially when we don't
have access to an Activity instance; therefore, in the following chapters, we are
going to discuss simpler and cleaner techniques to update the UI from a background
computing task.
public class MainActivity extends AppCompatActivity {
class SetSynonymResult implements Runnable {
String synonym;
SetSynonymResult(String synonym) {
this.synonym = synonym;
}
public void run() {
Log.d("AsyncAndroid", String.format("Sending synonym result %s on %d",
synonym, Thread.currentThread().getId()) + " !");
TextView tv = (TextView) findViewById(R.id.synonymTv);
tv.setText(this.synonym);
}
}
;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button search = (Button) findViewById(R.id.searchBut);
final EditText word = (EditText) findViewById(R.id.wordEt);
search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Runnable searchTask = new Runnable() {
#Override
public void run() {
String result = searchSynomim(word.getText().toString());
Log.d("AsyncAndroid", String.format("Searching for synonym for %s on %s",
word.getText(), Thread.currentThread().getName()));
runOnUiThread(new SetSynonymResult(result));
}
};
Thread thread = new Thread(searchTask);
thread.start();
}
});
}
static int i = 0;
String searchSynomim(String word) {
return ++i % 2 == 0 ? "fake" : "mock";
}
}
Source :
asynchronous android programming Helder Vasconcelos
This is how I use it:
runOnUiThread(new Runnable() {
#Override
public void run() {
//Do something on UiThread
}
});
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gifImageView = (GifImageView) findViewById(R.id.GifImageView);
gifImageView.setGifImageResource(R.drawable.success1);
new Thread(new Runnable() {
#Override
public void run() {
try {
//dummy delay for 2 second
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//update ui on UI thread
runOnUiThread(new Runnable() {
#Override
public void run() {
gifImageView.setGifImageResource(R.drawable.success);
}
});
}
}).start();
}
Try this: getActivity().runOnUiThread(new Runnable...
It's because:
1) the implicit this in your call to runOnUiThread is referring to AsyncTask, not your fragment.
2) Fragment doesn't have runOnUiThread.
However, Activity does.
Note that Activity just executes the Runnable if you're already on the main thread, otherwise it uses a Handler. You can implement a Handler in your fragment if you don't want to worry about the context of this, it's actually very easy:
// A class instance
private Handler mHandler = new Handler(Looper.getMainLooper());
// anywhere else in your code
mHandler.post(<your runnable>);
// ^ this will always be run on the next run loop on the main thread.
I am building a project in which i use async task to show progress bar.
I am using get() method to wait the main thread so we can do the other task before .
but progress bar is showing after completion of doInBackground thered.
I Want to show the loading bar when the loading starts.
It will dismiss when onPostExecute calls.
public class TempConverterActivity extends Activity {
pojo p;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button b= (Button) findViewById(R.id.btn);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
showResult();
}
});
}
private void showResult() {
try {
new LoadData().execute().get();
} catch (Exception e) {
Log.e("async brix--", e.getMessage());
}
runned();
}
private void runned() {
ArrayList<String> al = p.getData();
for (String str : al){
Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();
}
}
private class LoadData extends AsyncTask<Void, Void, Void> {
private final ProgressDialog dialog = new ProgressDialog(TempConverterActivity.this);
protected void onPreExecute() {
dialog.setMessage("Loading data...");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
protected void onPostExecute(final Void unused) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
#Override
protected Void doInBackground(Void... params) {
p = new pojo();
new SoapParser(p);
return null;
}
}}
Please help . Thanks in advance.
You can try following code,
progDailog = ProgressDialog.show(loginAct,"Process ", "please wait....",true,true);
new Thread ( new Runnable()
{
public void run()
{
// your code goes here
}
}).start();
Handler progressHandler = new Handler()
{
public void handleMessage(Message msg1)
{
progDailog.dismiss();
}
}
Edited: In my previous answer I suggested using a Handler; however, AsyncTask eliminates the need to do this which I didn't spot.
Why do you feel the need to call AsyncTask.get()? This is a blocking call, and you call this from the UI thread, thus it is ultimately a race condition as to whether it or onPreExecute() is run first.
I see no reason why you should call get() in this context. You want to call runned() after the AsyncTask completes, but you could do this by launching a new thread from onPostExecute(). Alternatively you could do as you do now, using get(), but call that from a new thread instead of the UI thread.
My application fetches some html code from the internet and when done , displays it on the devices screen. Since it takes about 3-4 seconds to do that , in this time the screen stays black , I'd like to use a progress dialog. This is my code :
package com.nextlogic.golfnews;
// ALL THE IMPORTS ....
public class Activity1 extends Activity {
private ProgressDialog progressDialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
progressDialog = ProgressDialog.show(Activity1.this, "", "Loading...");
new Thread()
{
public void run()
{
try
{
sleep(2000);
// HERE I'VE PUT ALL THE FUNCTIONS THAT WORK FOR ME
}
catch (Exception e)
{
Log.e("tag",e.getMessage());
}
// dismiss the progressdialog
progressDialog.dismiss();
}
}.start();
The program works but it doesn't display anything anymore. I have one error in logcat :
Only the original thread that created a view hierarchy can touch its views.
Could you please help me ? Thanks in advance.
The error is explicative enough. To update one visual object you must run the changes inside main thread. A quick and dirty fix could be calling the update code inside runOnUiThread().
However in your case I would use an AsyncTask to download and update the progress of the progress bar. The task has the property to run on UI thread when it ends (so you can update the views there, such as dismissing the progress dialog)
Here is an example how to use an AsyncTask to display a download progress dialog.
Update
Stackoverflow already has the answers to all your question. Here is an example of an AsyncTask to download some content and display the download progress. Just what you want.
Update 2
Ok here is your code using an AsyncTask:
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();
}
}
You need to do this way
runOnUiThread(new Runnable() {
public void run() {
// Do Your Stuff
}});
Dismiss your dialog like this:
Handler handler = new Handler();
handler.post(new Runnable(){
public void run(){
progressDialog.dismiss();
}
});
Create a UI thread after completing network operation
runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.dismiss();
}
});
The top answer works great, so here is an example to implement an AsyncTask in MonoDroid (thanks to Greg Shackels): http://mono-for-android.1047100.n5.nabble.com/AsyncTask-td4346647.html
Ok this is a very weird problem I am having, and I'm pretty sure that I am messing up somewhere, but I can't quite figure out where.
What I am trying is -
Schedule a Timer to execute a TimerTask every five seconds
The TimerTask in turn executes an AsyncTask (which in this case simple sleeps for a second before returning the static count of the number of AsyncTasks).
Finally, the aforementioned count is updated in the UI.
And of course, the appropriate Handlers and Runnables have been used to post asynchronous messages from other threads to the UI.
This code executes only once. I expect it to fire every 5 seconds. Here's the code.
Note: I had no idea what to do with the Looper. I put it there after trial and error!
public class TimerAsyncMixActivity extends Activity {
public static final String TAG = "TimerAsyncMix";
static int executionCount = 0;
Handler mHandler = new Handler();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Timer().schedule(new MyTimerTask(this), 0, 5000);
}
class MyAsyncTask extends AsyncTask<String, Void, Integer>{
#Override
protected Integer doInBackground(String... params) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ++executionCount;
}
#Override
protected void onPostExecute(Integer result) {
mHandler.post(new UpdateUiThread(TimerAsyncMixActivity.this, result));
super.onPostExecute(result);
}
}
}
class MyTimerTask extends TimerTask{
private TimerAsyncMixActivity tma;
public MyTimerTask(TimerAsyncMixActivity tma) {
this.tma = tma;
}
#Override
public void run() {
Looper.prepare();
Log.d(TimerAsyncMixActivity.TAG, "Timer task fired");
tma.new MyAsyncTask().execute();
Looper.loop();
Looper.myLooper().quit();
}
}
class UpdateUiThread implements Runnable{
int displayCount;
TimerAsyncMixActivity tma;
public UpdateUiThread(TimerAsyncMixActivity tma, int i) {
this.displayCount = i;
this.tma = tma;
}
#Override
public void run() {
TextView tv = (TextView) tma.findViewById(R.id.tvDisplay);
tv.setText("Execution count is : "+displayCount);
}
Can anyone point me to what I'm doing wrong?
techie, this is how I implemented similar things. I'm won't claim that this is the best way, but it has worked for me and doesn't look too bad.
I have the following code in my activity. I create an async task when the activity starts and I stop it onPause. The AsyncTask does whatever it needs to do, and updates the UI on onProgressUpdate() (which is run on the UI thread, so there's no need to use a Handler).
private Task task;
#Override
protected void onPause() {
task.stop();
task = null;
}
#Override
protected void onResume() {
task = new Task();
task.execute();
}
private class Task extends AsyncTask<Void, String, Void> {
private boolean running = true;
#Override
protected Void doInBackground(Void... params) {
while( running ) {
//fetch data from server;
this.publishProgress("updated json");
Thread.sleep(5000); // removed try/catch for readability
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
if( ! running ) {
return;
}
String json = values[0];
//update views directly, as this is run on the UI thread.
//textView.setText(json);
}
public void stop() {
running = false;
}
}
Do not use a timer. If your phone goes to sleep, the timer is suspended too. Use AlarmManager.