I would like to have a method that sends a udp broadcast and returns the responses in a list. In addition, a progress dialog is displayed during the broadcast and cancels when the method returns.
I have successfully accomplished the same thing with AsyncTask, but when I do that the class becomes very difficult to reuse because I have to do different things in the onPostExecute depending on where I start the AsyncTask. This is why I would much rather do it with a Thread, below is my method so far:
public static ArrayList<Device> broadcastForDevices(final String broadcastMessage,Context context){
final ProgressDialog p=ProgressDialog.show(context, null,"Broadcasting...",false);
final Handler handler= new Handler() {
#Override
public void handleMessage(Message message) {
Log.i(TAG,"Dismissing");
p.dismiss();
}
};
Thread broadcastForDevices=new Thread(new Runnable(){
#Override
public void run(){
DatagramSocket udpBroadcastSocket=null;
try{
udpBroadcastSocket= new DatagramSocket();
Log.i(TAG, "Created datagram socket");
}
catch(Exception e){
Log.i(TAG,"Exception "+e.getMessage());
}
detectedDevices=processDeviceResponses(sendBroadcastPackets(udpBroadcastSocket,broadcastMessage));
handler.sendEmptyMessage(0);
}
});
//Start then join normally defeats purpose of thread, but socket programming must be done off the UI thread
broadcastForDevices.start();
try {
broadcastForDevices.join();
} catch (InterruptedException e) {
Log.i(TAG, "Interrupted exception");
}
return detectedDevices;
}
The problem with above code is that the progress dialog never shows up. If I make the progress dialog a member variable of the class instead of final, the progress dialog shows up but is never cancelled. In both cases, the "Dismissing" gets logged somehow. Any ideas on how to make this work?
Using Thread:join() will not solve anything. The things you first did in onPostExecute you could now do in your Handler.
Related
I am trying to review the concept of Handler. So I simply create a Thread to update a ProgressBar and see if it would throw an exception.
Here's my code
#Override
public void onResume() {
super.onResume();
new Thread(){
#Override
public void run() {
super.run();
while (progressBar.getProgress() <100){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
progressBar.setProgress(pb.getProgress()+10);
}
}
}.start();
}
My question is simple. Why it doesn't throw any CalledFromWrongThreadException?
If it meant to be this way, should we forget about Handler when we deal with progress updating?
https://cs.android.com/android/platform/superproject/+/android-10.0.0_r30:frameworks/base/core/java/android/widget/ProgressBar.java;l=1610
Bad luck--ProgressBar has special support for updating its progress from another thread. That's why it doesn't throw something.
But because it's so specifically this operation that has this extra support, no to the second question. You wouldn't, in general, stop using a handler. For cases where, for example, you need to do one other little UI thing while updating the progress.
I'm calling methode doSomething() continuously with a thread.sleep(100). This happens in on the UIThread, so the UIthread gets unresponsive. What is the correct way in Android to run the method doSomething() or the entire someobject in a seperate thread?
public void loop(){
while(true){
someObject.doSomething();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Right now i'm using
new Thread(new Runnable() {
#Override
public void run() {
someObject.doSomething();
}
}).start();
This obviously creates a different thread for each iteration. I don't think this is the correct way. What is the correct way in Android?
new Thread(new Runnable() {
#Override
public void run() {
while(true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
someObject.doSomething();
}
}
}).start();
Since run never returns, the thread will never end and will loop forever. It will call doSomething roughly every 100 ms (as close as sleep will get, which isn't exact).
You can make your own Thread class, with Looper and Handler, posting your doSomething every 100ms:
public class MyThread extends Thread{
private Handler myHandler;
#Override
public void run(){
Looper.prepare();
myHandler = new Handler();
myHandler.post(doSomethingRunnable);
}
Runnable doSomethingRunnable = new Runnnable{
doSomething(); //or myHandler.postDelayed() first for greater accuracy, but only if doSomething doesnt take too long
myHandler.postDelayed(doSomethingRunnable, 100);
};
doSomething(){
thisStuff(thatStuff());
}
}
You can use AsyncTask. doInBackground() is called on a background thread and will not block UI. This is the preferred way for doing stuff on background threads.
For a long running task. You can use an IntentService and put your background code in onHandleIntent
You can use a basic thread but it may be hard to manage. You can read more about threads in android here
In OnResume(), I make web service call in thread here i used progress bar for indicating the process it works fine but suppose i uses the app after sometime i put the device idle after that open the app once again this time progress bar is not dismissed.It's not regularly happens sometimes it happens. Why?
How can i make it to away from this? If you need more info plz let me know.
Code :
Edit:
public void onResume()
{
super.onResume();
pdMessages = ProgressDialog.show(getParent(), "", "Please wait...", true);
Thread thImportbtn = new Thread()
{
public void run()
{
try
{
//Get internal messages
strInternalInboxWSR = GetInternalInboxMessages();
} catch (SoapFault e) {
e.printStackTrace();
}
dh_Messages_Handler.post(checked_internalinbox_response);
handler.sendMessage(handler.obtainMessage());
}
};
thImportbtn.start();
}
private Handler handler = new Handler()
{
#Override
public void handleMessage ( Message message )
{
pdMessages.dismiss();
}
};
You can use Handler Class to dismiss your ProgressDialog, like below
private Handler handler = new Handler()
{
#Override
public void handleMessage ( Message message )
{
progressDialog.dismiss();
}
};
you can use following statement to call Handler class,
handler.sendMessage(handler.obtainMessage());
You are Trying To Dismiss ProgressDialog in Non-UI Thread, So can't Dismiss proper.
you should put your dismiss code( pdMessages.dismiss();) in Handler Using Overriding handleMessage method
Use AsyncTask is better.
I'm new to Android development. I've be working on Swing and SWT for several years. Both Swing and SWT has a stratage to execute code in UI thread sync and async. The typical usage is doing some time-consume staff in one thread then display the result in UI thread async.
So my question is, is there similiar stratage in Android? Here is my code. Parameter runnable is some time-consume code. This method will display a waiting dialog during the execution then EXPECT to show a Toast after it is finished. But the Toast need to be show in UI thread. So how to do that?
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
// TODO: How to display a Toast message here? execute some code in UI Thread.
}
});
}
And is there some words about Android UI system? Such as is it Thread-Safe, how thread works together and so on. Many Thanks!
There are several ways for doing that,
AsyncTask -
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers. Example for using AsyncTask
Service -
A Service is an application component representing either an
application's desire to perform a longer-running operation while not
interacting with the user or to supply functionality for other
applications to use. Example for Using Service.
IntentService -
IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand. Clients send requests
through startService(Intent) calls; the service is started as needed,
handles each Intent in turn using a worker thread, and stops itself
when it runs out of work. Example for using IntentService.
You can use AsyncTask like this.
To call AsyncTask
new getAsynctask().execute("");
and here is the class for geting result.
class getAsynctask extends AsyncTask<String, Long, Integer> {
protected void onPreExecute() {
super.onPreExecute();
loading = ProgressDialog.show(Pass.this, null, "Please wait...");
}
protected Integer doInBackground(String... params) {
try {
// do your coding
return null;
} catch (Exception e) {
return null;
}
}
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
try {
if (loading != null && loading.isShowing())
loading.dismiss();
} catch (Throwable t) {
Log.v("this is praki", "loading.dismiss() problem", t);
}
}
}
Whenever you are working with Separate thread which is not your UI thread the best way is to use Handler. Whenever you want to intimate user from your Thread, suppose a progress then send a message to Handler to so. Inside Handler you can handle message and write a code snippet to Change anything on UI. This is the preferred way for Android. see these link1 , link2 & link3
You use this AsynTask as a inner class of your activity. In do in background do the time consuming task you want to do and then in on postexecute you can show the text message.
call this from your main activity
initTask = new InitTask();
initTask.execute(this);
protected class InitTask extends AsyncTask<Context, Integer, String> {
#Override
protected String doInBackground(Context... params) {
// Do the time comsuming task here
return "COMPLETE!";
}
// -- gets called just before thread begins
#Override
protected void onPreExecute() {
super.onPreExecute();
}
// -- called from the publish progress
// -- notice that the datatype of the second param gets passed to this
// method
#Override
protected void onProgressUpdate(Integer... values) {
}
// -- called if the cancel button is pressed
#Override
protected void onCancelled() {
super.onCancelled();
}
// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Show the toast message here
}
}
Use a handler:
static final int SHOW_TOAST = 0;
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
handler.sendMessage(handler.obtainMessage(SHOW_TOAST));
}
});
}
public Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_TOAST:
//Toast here
break;
}
}
};
The Painless threading article from the android developer resources provides different alternatives depending on the specific SDK version.
In My application I want to check data after every second, using service.
I have tried to use Timer but it doesn't allow me to use 'runOnUiThread' in service.
In Activity Timer works fine.
or
Is there any other way to trace database at every seconds?
Implement a Runnable, that way you can use the runOnUiThread(runnable) functionality.
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
//do ui update
}
};
Edit: try this: More efficient way of updating UI from Service than intents?
Edit2: http://developer.android.com/resources/articles/timed-ui-updates.html
Use thread u can trace the data base every time
try{
thread=new Thread()
{
#Override
public void run() {
while(set) {
thread_Run();
}
}
};
}
catch(Exception e)
{
Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
}