My app receives messages and has to schedule multiple replies one after another each with a different delay. What is the best way to have about 2000 delayed tasks with different delays? It seems like Android can't run that much handlers at the same time due to limited ressources.
Any ideas?
Thanks in advance.
Code simplified:
class TimedTask extends TimerTask { //runs every 10 seconds and checks for new contacts in queue to reply to (contacts can go up to 500 ones)
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(SendMessagesService.this);
String contacts = sp.getString("contacts", ""); //queued by another Thread
String contacts_array[] = contacts.split(",");
for (String contact : contacts_array) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
String message = sp.getString("message1",""); //there are different messages with different delays, depending on which were already sent
ReceiveContactsAdapter mDbHelper = new ReceiveContactsAdapter(SendMessagesService.this);
mDbHelper.open();
mDbHelper.sendMessages(message, contact);
mDbHelper.close();
}
}, delay); //delay depends on which message will be sent
}
}
You can use thread.sleep(milisec) instead. It delays the thread for the particular time.
#Override
public void run()
{
while (!Thread.interrupted())
try
{
Thread.sleep(1000);
MainActivity.this.runOnUiThread(new Runnable()
{
#Override
public void run()
{
////
}
});
}
catch (InterruptedException e)
{
}
}
})).start();
I have a issue with using a timer on a listview.
In the list item I showed using sqlite values. There is a textview which showing time difference of last updated time of the data and current time. i have to show it in every one second. so the user can know how long he updated the record.
I tried this in several ways.
First way
I tried to add timer in adapter class. so for every item new timer is created. so application crashed because of many timers run simultaneously.
Second way
I tried using adapter.notifyDataSetChanged() way. Like as this.
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
if (adapterChatThread != null) {
adapter.notifyDataSetChanged();
}
timerHandler.postDelayed(this, 1000); // run every second
}
};
timerRunnable.run();
I move to another activity when click on list item and user can come back to this Activity.
so in Onresume I used
timerHandler.postDelayed(timerRunnable, 500);
and OnPause
timerHandler.removeCallbacks(timerRunnable);
Issue is data is not showing well. I mean in every second data difference is not one second. some time differnce is 2sec, 5 sec, .. etc.
means timer is not working as I expected.
Third way
I used a asynctask and call it in every second using a timer.
class ThreadTimer extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void result) {
if (adapter != null)
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
}
I called this as in here
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
new ThreadTimer().execute();
timerHandler.postDelayed(this, 1000); // run every second
}
};
timerRunnable.run();
previous issue triggered. (data not showing well)
Fourth way
Using AsyncTask as this
class ThreadTimer extends AsyncTask<Void, Void, Void> {
void Sleep(int ms) {
try {
Thread.sleep(ms);
} catch (Exception e) {
}
}
#Override
protected Void doInBackground(Void... params) {
while (threadRun) {
Sleep(1000);
return null;
}
return null;
}
#Override
protected void onPostExecute(Void result) {
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
}
I called this class in OnResume.
In on pause I set threadRun= false;
issue is same.
please help me.
My requirement is update list item in every second.
Thank you.
edit
here is my adapter class textview update code.
Date lastUpdatedTime;
final ChatThreadDAO ctd = new ChatThreadDAO();
long timeForNextResponse = ctd.getLastRespondedTime(vct.get(position).getThread_id());
try {
if (vct.get(position).getThread_read_status() == 1 && timeForNextResponse > 0) {
final long respTime = timeForNextResponse;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
lastUpdatedTime = formatter.parse(vct.get(position).getLast_updated_time());
final long timeDiff = (new Date()).getTime() - lastUpdatedTime.getTime();
if (timeDiff <= respTime) {
timeForNextResponse = respTime - timeDiff;
ctd.updateTimeRespondToLastMsg(vct.get(position).getThread_id(), timeForNextResponse);
holder.tvChatTimer.setVisibility(View.VISIBLE);
holder.tvChatTimer.setText(timeForNextResponse / 1000 + "");
} else {
ctd.updateTimeRespondToLastMsg(vct.get(position).getThread_id(), 0);
}
} else {
holder.tvChatTimer.setVisibility(View.INVISIBLE);
}
} catch (ParseException e) {
e.printStackTrace();
}
here vct is
Vector vct;
I assign the values to vector in adapter class constructer.
Here is an example similar to your case.
private class connectionControl extends Thread {
boolean stop_ = false;
public void stop_() {
this.stop_ = true;
}
public void run() {
System.out.println("Thread started:" + getClass().getSimpleName());
while(!this.stop_) {
try {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Calendar c = Calendar.getInstance();
int rightNow = c.get(Calendar.SECOND) + c.get(Calendar.MINUTE)*60;
if(rightNow - lastUpdatedTime > 10) {
wirelessIcon.setImageResource(R.drawable.wirelessred);
}
else if(rightNow - lastUpdatedTime > 5) {
wirelessIcon.setImageResource(R.drawable.wirelessyellow);
}
else {
wirelessIcon.setImageResource(R.drawable.wirelessgreen);
}
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Thread stoped:" + getClass().getSimpleName());
}
}
You set your lastUpdatedTime the same way you created rightNow whenever you call notifyDataSetChanged() method of your adapter.
On click of a button, I want to open a dialog box. On that dialog box I want to set the text dynamically (somewhat like a stopwatch) with the text which will come via a loop. Could someone please guide me with sample code? I tried many examples given on the net but not able to successfully achieve the result.
//Button where the action starts
public void onClickStart(View v) {
final Dialog dialog = new Dialog(MainActivity.this);
dialog.setContentView(R.layout.activity_details);
dialog.setTitle("Your Step Details");
dialog.show();
DisplayTask dd= new DisplayTask();
dd.execute();
}
public void doWork(){
final Handler handler=new Handler();
new Thread(new Runnable (){
boolean isRunning=true;
#Override
public void run() {
while(isRunning){
try{
handler.post(new Runnable(){
#Override
public void run() {
try{
TextView txtCurrentTime= (TextView)findViewById(R.id.txtLeft);
Date dt = new Date();
int hours = dt.getHours();
int minutes = dt.getMinutes();
int seconds = dt.getSeconds();
String curTime = hours + ":" + minutes + ":" + seconds;
txtCurrentTime.setText(curTime);
}catch (Exception e) {}
}
});
}catch(Exception e){
}
}
}
}).start();
}
public class DisplayTask extends AsyncTask<Void , Void, Void> {
protected void onPostExecute(){
MainActivity main= new Mai`enter code here`nActivity();
main.doWork();
}
#Override
protected Void doInBackground(Void... params) {
onPostExecute();
return null;
}
}
If you want to do something on a timer, AsyncTask isn't the right method. Use a Handler, and post a message to it using postMessageDelayed. This will let you do something in a few milliseconds/seconds, but it will happen on the UI thread.
I'm developing an Android 2.3.3 application and I need to run a method every X seconds.
In iOS, I have NSTimer, but in Android I don't know what to use.
Someone have recommend me Handler; another recommend me AlarmManager but I don't know which method fits better with NSTimer.
This is the code I want to implement in Android:
timer2 = [
NSTimer scheduledTimerWithTimeInterval:(1.0f/20.0f)
target:self
selector:#selector(loopTask)
userInfo:nil
repeats:YES
];
timer1 = [
NSTimer scheduledTimerWithTimeInterval:(1.0f/4.0f)
target:self
selector:#selector(isFree)
userInfo:nil
repeats:YES
];
I need something what works like NSTimer.
What do you recommend me?
The solution you will use really depends on how long you need to wait between each execution of your function.
If you are waiting for longer than 10 minutes, I would suggest using AlarmManager.
// Some time when you want to run
Date when = new Date(System.currentTimeMillis());
try {
Intent someIntent = new Intent(someContext, MyReceiver.class); // intent to be launched
// Note: this could be getActivity if you want to launch an activity
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
0, // id (optional)
someIntent, // intent to launch
PendingIntent.FLAG_CANCEL_CURRENT // PendingIntent flag
);
AlarmManager alarms = (AlarmManager) context.getSystemService(
Context.ALARM_SERVICE
);
alarms.setRepeating(
AlarmManager.RTC_WAKEUP,
when.getTime(),
AlarmManager.INTERVAL_FIFTEEN_MINUTES,
pendingIntent
);
} catch(Exception e) {
e.printStackTrace();
}
Once you have broadcasted the above Intent, you can receive your Intent by implementing a BroadcastReceiver. Note that this will need to be registered either in your application manifest or via the context.registerReceiver(receiver, intentFilter); method. For more information on BroadcastReceiver's please refer to the official documentation..
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
System.out.println("MyReceiver: here!") // Do your work here
}
}
If you are waiting for shorter than 10 minutes then I would suggest using a Handler.
final Handler handler = new Handler();
final int delay = 1000; // 1000 milliseconds == 1 second
handler.postDelayed(new Runnable() {
public void run() {
System.out.println("myHandler: here!"); // Do your work here
handler.postDelayed(this, delay);
}
}, delay);
Use Timer for every second...
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//your method
}
}, 0, 1000);//put here time 1000 milliseconds=1 second
You can please try this code to call the handler every 15 seconds via onResume() and stop it when the activity is not visible, via onPause().
Handler handler = new Handler();
Runnable runnable;
int delay = 15*1000; //Delay for 15 seconds. One second = 1000 milliseconds.
#Override
protected void onResume() {
//start handler as activity become visible
handler.postDelayed( runnable = new Runnable() {
public void run() {
//do something
handler.postDelayed(runnable, delay);
}
}, delay);
super.onResume();
}
// If onPause() is not included the threads will double up when you
// reload the activity
#Override
protected void onPause() {
handler.removeCallbacks(runnable); //stop handler when activity not visible
super.onPause();
}
If you are familiar with RxJava, you can use Observable.interval(), which is pretty neat.
Observable.interval(60, TimeUnits.SECONDS)
.flatMap(new Function<Long, ObservableSource<String>>() {
#Override
public ObservableSource<String> apply(#NonNull Long aLong) throws Exception {
return getDataObservable(); //Where you pull your data
}
});
The downside of this is that you have to architect polling your data in a different way. However, there are a lot of benefits to the Reactive Programming way:
Instead of controlling your data via a callback, you create a stream of data that you subscribe to. This separates the concern of "polling data" logic and "populating UI with your data" logic so that you do not mix your "data source" code and your UI code.
With RxAndroid, you can handle threads in just 2 lines of code.
Observable.interval(60, TimeUnits.SECONDS)
.flatMap(...) // polling data code
.subscribeOn(Schedulers.newThread()) // poll data on a background thread
.observeOn(AndroidSchedulers.mainThread()) // populate UI on main thread
.subscribe(...); // your UI code
Please check out RxJava. It has a high learning curve but it will make handling asynchronous calls in Android so much easier and cleaner.
With Kotlin, we can now make a generic function for this!
object RepeatHelper {
fun repeatDelayed(delay: Long, todo: () -> Unit) {
val handler = Handler()
handler.postDelayed(object : Runnable {
override fun run() {
todo()
handler.postDelayed(this, delay)
}
}, delay)
}
}
And to use, just do:
val delay = 1000L
RepeatHelper.repeatDelayed(delay) {
myRepeatedFunction()
}
new CountDownTimer(120000, 1000) {
public void onTick(long millisUntilFinished) {
txtcounter.setText(" " + millisUntilFinished / 1000);
}
public void onFinish() {
txtcounter.setText(" TimeOut ");
Main2Activity.ShowPayment = false;
EventBus.getDefault().post("go-main");
}
}.start();
Here I used a thread in onCreate() an Activity repeatly, timer does not allow everything in some cases Thread is the solution
Thread t = new Thread() {
#Override
public void run() {
while (!isInterrupted()) {
try {
Thread.sleep(10000); //1000ms = 1 sec
runOnUiThread(new Runnable() {
#Override
public void run() {
SharedPreferences mPrefs = getSharedPreferences("sam", MODE_PRIVATE);
Gson gson = new Gson();
String json = mPrefs.getString("chat_list", "");
GelenMesajlar model = gson.fromJson(json, GelenMesajlar.class);
String sam = "";
ChatAdapter adapter = new ChatAdapter(Chat.this, model.getData());
listview.setAdapter(adapter);
// listview.setStackFromBottom(true);
// Util.showMessage(Chat.this,"Merhabalar");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
In case it needed it can be stoped by
#Override
protected void onDestroy() {
super.onDestroy();
Thread.interrupted();
//t.interrupted();
}
I do it this way and it works fine (the code is written in Kotlin):
private lateinit var runnable: Runnable
private var handler = Handler(Looper.getMainLooper())
private val repeatPeriod: Long = 10000
Then reinit the runnable from inside your function
runnable = Runnable {
// Your code goes here
handler.postDelayed(runnable, repeatPeriod)
}
handler.postDelayed(runnable, repeatPeriod)
Note that if you don't postDelay twice the handler, the loop is not going to be intinity!
In Kotlin, you can do it this way with a Runnable:
private lateinit var runnable: Runnable
private var handler = Handler(Looper.getMainLooper())
private val interval: Long = 1000
private var isRunning = false
val runnable = object : Runnable {
override fun run() {
// Do something every second
function()
// Call your runnable again after interval
handler?.postDelayed(runnable(this, interval))
}
}
// Call your function once
if (!isRunning) {
handler?.postDelayed(runnable, interval)
isRunning = true
}
// Remove your repeatedly called function
if (isRunning) {
handler?.removeCallbacks(runnable)
isRunning = false
}
My web service response comes in this format: 19/2/2011. I want to compare this web service date to my own calendar date.
Is there any answer and how to highlight that date?
final Thread t = new Thread(new Runnable() {
#Override
public void run() {
parseData();
}
});
t.start();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//Split strings here and check them
}
});
t1.start();
If you have both the date in strings you can break it up into day, time , year token and then can compare the strings....this will be a easy and raw approach to do this