I have question regarding the service and activity.
I have one service which calls some other class to get contacts from phone, and activity where the contacts will be placed. What is the best thing to do:
1 this: On bound Activity "ask" in infinite loop for status from service like this:
Thread trdTest = new Thread(new Runnable() {
public void run() {
boolean done= true;
while(done){
if (service.status == Constants.GETTING_CONTACTS_DONE_OK){
handler.sendEmptyMessage(0);
done= false;
}else if (service.status == Constants.GETTING_CONTACTS_ERROR_NOTOK){
handler.sendEmptyMessage(1);
done= false;
}
}
}});
trdTest.start();
2: this: Create cistom event in service and fire event when getting users is done. Of course the bounded activity will listen for that event
Thanx for the answers.
Running loops like that will probably slow down many things and is not a good idea. The second approach seems to me like a much better idea.
Related
I am new to threading and i went through many post in stack overflow and find many solution for my problem but i am not sure which one is best for which condition.
First thing first, my problem is that i want to update one JSON file
when all threads are done with the bitmap generation at a specific path so
that i can get that all those image and update JSON file. So in
simple word my i want to run some code when all thread are done with it
execution and major requirement is that i don't want my main to be blocked because of this.
What i have found out
thread. join
excutorServive
android-priority-jobQueue (link)
Mutex in threadpool ( also let me know if any other is there)
I am confused which one is the best way to tackle my problem. if any
android expert out there can summarise that for following the two
scenerio what is the best available in android.
wait till when all thread completes
don't wait and get informed when all completes
You can have counter for your threads, after each thread is complete check how many have already completed, if not all completed, increment the number of completed threads and the last thread to complete will then run the piece of code.
You can do it like this.
In your thread:
private Runnable runnableThread= new Runnable() {
#Override
public void run() {
try {
if (lastThreadDone){
handler.sendEmptyMessage("SUCCESS");
}
}
catch (Exception ex) {
throws ex;
}
}
};
lastThreadDone is boolean which will become true if the process is done, this is base on how you implement it.
then in you handler:
#SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
try {
switch (msg.what) {
case "SUCCESS": {
// your code here
break;
}
case "FAIL":
break;
default:
break;
}
}
catch (Exception ex) {
throw ex;
}
super.handleMessage(msg);
}
};
I would use a completion service and then poll until all tasks are finished. When they are done, the json file gets updated. The problem is that you need to do this async or you risk to block the ui. Therefore I would encapsulate the work with the completion service inside an intent service. If you need to update the ui you then can post local broadcasts from the intent service.
Furthermore for you cases
wait till when all thread completes
only do this when you are already on a background thread like intent service or async task
don't wait and get informed when all completes
implies the case above. Do the work async and notify the ui or some listening component with broadcasts, content observers, handlers or the 'onPostExecute' if you are using async task.
I have some code which sets a timer, but if a user sets the timer while it is in use I need to remove the runnable which runs the timer and start it again. But when no handler callback runnable exists and this code is called it crashes my application. So I need to check if a handler is running, if so then end it and restart it, but looking through the documentation and other Stackoverflow questions, I cannot see if this is possible.
Here is my code, I have commented around the code which should only be executed if a handler runnable exists:
submitTimer.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
String s = timer.getText().toString();
if(!s.equals(""))
{
//I NEED TO CHECK A RUNNABLE HANDLER EXISTS AND IF SO THEN RUN THIS CODE, IF NOT IGNORE THIS CODE
Map.handler.removeCallbacks(Map.getRunnable());
Map.runnable.run();
//I NEED TO CHECK A RUNNABLE HANDLER EXISTS AND IF SO THEN RUN THIS CODE, IF NOT IGNORE THIS CODE
int l = Integer.parseInt(s);
Map.timerinmins = l;
timer.setHint("Current Timer is "+Map.timerinmins);
timer.setText("");
Toast.makeText(Preferences.this, "Timer is set!", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(Preferences.this, "No value was entered", Toast.LENGTH_SHORT).show();
}
}
});
Can anyone help me figure out a way of checking the handlers current state?
Referring to Jay Snayder's reply:
Since there are cases in which Map.handler.hasMessages(CALLBACK_PRESENT_INTEGER) returns false even though Map.handler.sendEmptyMessage(CALLBACK_PRESENT_INTEGER) has been called (happened to me, too), it may be safer to use a boolean to determine whether the handler has callbacks or not.
So, the code logic is something very simple like this:
...
boolean callbackPresent = false;
...
if(!callbackPresent) {
// do what you have to do in case the handler doesn't have callbacks
// right before adding a callback to the handler, call:
callbackPresent = true;
} else {
// do what you have to do in case the handler has callbacks
// right before removing the callbacks from the handler, call:
callbackPresent = false;
}
...
I'm using this solution in an app and it's working perfectly.
If you want you could send an empty message when you first put a callback in and then check for that message in the handler. This empty message could represent that there is a callback present. Removing that message later could then be used similarly to see if the callback is still there. Don't have a relevant situation such as this to go from, but thought that I would at least try and share a possibility.
...
Map.handler.sendEmptyMessage(CALLBACK_PRESENT_INTEGER);
...
if(Map.handler.hasMessages(CALLBACK_PRESENT_INTEGER)
...
Map.handler.removeMessage(CALLBACK_PRESENT_INTEGER);
...
This is probably not ideal, but could be a potential solution if you have access to your handler from the point where your callback is used. Not sure if there is a direct way to find out.
Handler class has a method
boolean hasCallbacks(#NonNull Runnable runnable)
to check if there are any pending posts of messages with callback runnable in the message queue.
It exists since SDK 16 but it's hidden prior to SDK 29.
HandlerCompat class has the compatible version of this method for SDKs 16+:
boolean hasCallbacks(handler, runnable)
I'm pretty new to this, so sorry if my question might be trivial, and I'm sure this is basic stuff, but really I couldn't find a solution.
I'd like to realize an autorefresh in an active activity. I have a BT-service running in background and need a confirmation for some received data through mHandler. If it receives the expected I want to change the string of a textview, right now I'm using an extra button, but it's the ugliest way.
So I need a loop inside the activity, but what should I use? which action listener?
ok what you can do is you can create a broadcast reciever in your activity. Write this code in you oncreate. fix it actually i am at home so you need to fix it i m giving you idea.
BroadcastReciever broadcast_obj = new BroadcastReciever (
#overrieded
onRecieve(Intent intent) {
String action = intent.getAction();
if(action == "my_bt_action") {
//UPDATE YOUR TEXTVIEW AND DO WHATEVER WORK YOU WANT.
}
});
Now you need to register your broadcast for that just put these line in your oncreate after creating Broadcast reciever which we have just done.
registerREciever(broadcast_obj, new IntentFilter("my_bt_action");
now you need to send your broadcast when your service will perform your calculation or your task for that it is simple.
Intent intent = new Intent (getApplictionContext,"my_bt_action");
sendBroadcast(intent);
from above code you can easily communicate between your activity and service.
hope it will work.
Maybe you can try a loop inside a thread
boolean update = false; // control the state to update textview
new Thread(new Runnable(){
void run(){
while(true){
if(!update){
...
textview.setText("something.");
...
update = true;
}
}
}
}.start();
I can't understand the implementation of a while loop in android.
Whenever I implement a while loop inside the onCreate() bundle, (code shown below)
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
TextView=(TextView)findViewById(R.id.TextView);
while (testByte == 0)
updateAuto();
}
nothing boots up, and the program enters a "hanging" state after a while and I can't understand why. Testbyte is as follows:
byte testByte == 0;
and updateAuto() is supposed to update the code per 1 second and display inside the textView portion. I've been using setText inside updateAuto() as shown below and everything works fine, but once i implement the while loop all i see is a black screen and then an option to force close after a few seconds due to it "not responding".
TextView.setText(updateWords);
I've changed it to a button format (meaning i have to click on the button to update itself for now), but i want it to update itself instead of manually clicking it.
Am i implementing the while loop in a wrong way?
I've also tried calling the while loop in a seperate function but it still gives me the black screen of nothingness.
I've been reading something about a Handler service... what does it do? Can the Handler service update my TextView in a safer or memory efficient way?
Many thanks if anyone would give some pointers on what i should do on this.
Brace yourself. And try to follow closely, this will be invaluable as a dev.
While loops really should only be implemented in a separate Thread. A separate thread is like a second process running in your app. The reason why it force closed is because you ran the loop in the UI thread, making the UI unable to do anything except for going through that loop. You have to place that loop into the second Thread so the UI Thread can be free to run. When threading, you can't update the GUI unless you are in the UI Thread. Here is how it would be done in this case.
First, you create a Runnable, which will contain the code that loops in it's run method. In that Runnable, you will have to make a second Runnable that posts to the UI thread. For example:
TextView myTextView = (TextView) findViewById(R.id.myTextView); //grab your tv
Runnable myRunnable = new Runnable() {
#Override
public void run() {
while (testByte == 0) {
Thread.sleep(1000); // Waits for 1 second (1000 milliseconds)
String updateWords = updateAuto(); // make updateAuto() return a string
myTextView.post(new Runnable() {
#Override
public void run() {
myTextView.setText(updateWords);
});
}
}
};
Next just create your thread using the Runnable and start it.
Thread myThread = new Thread(myRunnable);
myThread.start();
You should now see your app looping with no force closes.
You can create a new Thread for a while loop.
This code will create a new thread to wait for a boolean value to change its state.
private volatile boolean isClickable = false;
new Thread() {
#Override
public void run() {
super.run();
while (!isClickable) {
// boolean is still false, thread is still running
}
// do your stuff here after the loop is finished
}
}.start();
I have a service which sends continously values to an activity through some custom event listeners.
Here everything works fine. Certain values are displayed in my activity as expected, but some others make the application to crash. This is because some of the incoming data is calculated inside a normal thread (that I cannot have access for changing it), and I know I have to use a handler here, but as far as I tried the app still crashing.
more graphically I would like to do the following
onValuesChanged(float val) {
myTextView.setText( Float.toString(val) )
}
where val is calculated in a normal thread, but of course it makes crash the app when doing the setText.
Any suggestions?
Use AsyncTask instead of Thread and in the onPostExecute() you can update the UI.
or use Activity.runOnUiThread(new Runnable() {
void run() {
// do something interesting.
}
});
hey u can send a custom broadcast from your service like this
Intent mintent = new Intent();
mintent.setAction("com.action");
mintent.putExtra("name", "value");
sendBroadcast(mintent);
and register a receiver in your activity which will get the value from incoming intent and then call the handler like this to update the UI ..plese parse the int to string at receiving
myTextView.post(new Runnable() {
public void run() {
myTextView.setText( Float.toString(val) )
}
});
Every time you send a broadcast to your activity and it will update the ui ..
However the above mentioned way is also right but if you have to stay with service then go for this way else above......