setText not working in while loop - java

My app gets traffic updates from an API (this works) and returns a JSON array, which i'm then taking each element of in a while loop (JSONobject) and attempting to update a TextView with each result every 5 seconds.
However, my script is waiting 15 seconds and then updating to the last value. I've done some research and it says to use asynctask, which I have done, but it has not made a difference.
I've added System.out.println(thestring_to_update_to), and this is working as I would like my app to do (changing every 5 seconds).
The following is in a try/catch block :
JSONArray TrafficInformation = new JSONArray(response);
int TrafficEvents = TrafficInformation.length();
int TrafficEvent = 0;
JSONObject CurrentEvent = new JSONObject();
do{
CurrentEvent = new JSONObject(TrafficInformation.getString(TrafficEvent));
TextView affected_route = (TextView)findViewById(R.id.disrupted_route);
try {
Object[] passTo = new Object[1];
passTo[0] = CurrentEvent.getString("9");
System.out.println(passTo[0]);
new tasker().doInBackground(passTo);
TrafficEvent++;
Thread.sleep(5000);
} catch (Exception e){
Toast.makeText(LiftShare.this, "There was an error with getting traffic info.", Toast.LENGTH_LONG).show();
}
} while (TrafficEvent < TrafficEvents);
I also have this public class
public class tasker extends AsyncTask {
#Override
protected Object[] doInBackground(Object[] Objects) {
TextView affected_route = (TextView)findViewById(R.id.disrupted_route);
affected_route.setText(Objects[0].toString());
return null;
};
}
this is the JSONArray that goes in to the code (It is formatted correctly)
Array
(
[0] => {"1":"Congestion","2":"Minor Disruption - up to 15 minutes delay","3":"Location : The M3 eastbound exit slip at junction J9 . \nReason : Congestion. \nStatus : Currently Active. \nReturn To Normal : Normal traffic conditions are expected between 11:30 and 11:45 on 25 January 2018. \nDelay : There are currently delays of 10 minutes against expected traffic. \n","7":"M3 J9 eastbound exit | Eastbound | Congestion","9":"M3","10":"South East","11":"Hampshire","14":"2018-01-25T11:22:38+00:00"}
[1] => {"1":"Overturned Vehicle","2":"Severe Disruption - in excess of 3 hours delay or road closure","3":"Location : The M3 westbound between junctions J8 and J9 . \nReason : Clearing the scene of an overturned vehicle. \nStatus : Currently Active. \nTime To Clear : The event is expected to clear between 14:45 and 15:00 on 25 January 2018. \nReturn To Normal : Normal traffic conditions are expected between 14:45 and 15:00 on 25 January 2018. \nLanes Closed : All lanes are closed. \nPrevious Reason : Following an earlier accident. \n","7":"M3 westbound between J8 and J9 | Westbound | Overturned Vehicle","9":"M3","10":"South East","11":"Hampshire","14":"2018-01-25T06:51:12+00:00"}
[2] => {"1":"Congestion","2":"Moderate Disruption - between 15 minutes and 3 hours delay","3":"Location : The A34 southbound between the A272 and the junction with the M3 . \nReason : Congestion. \nStatus : Currently Active. \nReturn To Normal : Normal traffic conditions are expected between 12:45 and 13:00 on 25 January 2018. \nDelay : There are currently delays of 40 minutes against expected traffic. \n","7":"A34 southbound within the A272 junction | Southbound | Congestion","9":"A34","10":"South East","11":"Hampshire","14":"2018-01-25T07:48:23+00:00"}
)
How can I get the textview to update to the new value every 5 seconds?

You have to use
new tasker().execute(passTo);
to start asynctask as a thread otherwise, with current implementation, it will just act as a normal method call
Note: you cannot update UI from background thread i.e. inside doInBackground, instead override onPostExecute which runs on UI thread
#Override
protected Object[] doInBackground(Object[] Objects) {
TextView affected_route = (TextView)findViewById(R.id.disrupted_route);
//affected_route.setText(Objects[0].toString()); crash, instead do this in onPostExecute
return null;
};
Update : you can use postDelayed with delay to update UI after some interval
int i = 0;
affected_route.postDelayed(new Runnable() {
public void run() {
textView.setText(yourText);
}
},i+=5000);

AsyncTask seems like a overkill for your requirement as you are not really doing any work in the background. You could schedule the text to be updated after a time period using a Handler (from android.os) like this:
Handler handler = new Handler(Looper.getMainLooper());
Runnable textUpdater = new Runnable() {
#Override
public void run() {
// this needs to execute in the UI thread
affected_route.setText(lastUpdate);
}
};
String lastUpdate = "Store your last update here";
void updateText(){
handler.postDelayed(textUpdater, 5000);
}

Related

Java : how to send x emails per minute

I need to send a customized email to 400 clients.
I am doing this :
for (Client c : clients){
setUpEmail(c);
sendMail(c);
}
My problem is that my email provider authorizes me to send only 10 emails per minute. How could I do that in the loop?
Thanks.
Use Guava's RateLimiter.
If you already have Guava in your library path, or if you're interested in adding it, you can use this solution:
RateLimiter rateLimiter = RateLimiter.create(10/60d); // 10 permits per 60 seconds.
for (Client c : clients){
setUpEmail(c);
rateLimiter.acquire(1);
sendMail(c);
}
Your kind of problem is exactly why RateLimiter was created.
Use a counter and wait for a minute when ten mails were sent:
int counter = 0;
for (Client c : clients){
counter++;
setUpEmail(c);
sendMail(c);
if(counter%10==0){
Thread.sleep(60*1000); // wait a minute
}
}
This is not ideal since you may lost some time, e.g. when sending ten mails needs 20 seconds, you only may wait 40 seconds before starting a new bulk.
Another option would be to wait between each mail so that the time for 10 mails is at least 60 seconds:
for (Client c : clients){
setUpEmail(c);
sendMail(c);
Thread.sleep(6*1000); // wait 6 seconds
}
And a more sophisticated one:
int counter = 0;
long start = System.currentTimeMillis();
for (Client c : clients){
counter++;
setUpEmail(c);
sendMail(c);
if(counter%10==0){
long needed = System.currentTimeMillis() - start; // ms needed for ten mails
Thread.sleep(60*1000 - needed); // wait rest of the minute
start = System.currentTimeMillis(); // start of the next bulk
}
}
Deque clientsDeque = new ArrayDeque(clients);
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () => {
for (int i=0; i<10; i++){
Client c = clientsDeque.poll();
setUpEmail(c);
sendMail(c);
}
}
executor.schedule(task, 60, TimeUnit.SECONDS);

Is there an alternative for GroupReduceFunction running apache-flink java in parallel?

The code below is running locally but not on the cluster. It hangs on GroupReduceFunction and do not terminates even after hours (it takes for large data ~ 9 minutes to compute locally). The last message in the log:
GroupReduce (GroupReduce at main(MyClass.java:80)) (1/1) (...) switched from DEPLOYING to RUNNING.
The code fragment:
DataSet<MyData1> myData1 = env.createInput(new UserDefinedFunctions.MyData1Set());
DataSet<MyData2> myData2 = DataSetUtils.sampleWithSize(myData1, false, 8, Long.MAX_VALUE)
.reduceGroup(new GroupReduceFunction<MyData1, MyData2>() {
#Override
public void reduce(Iterable<MyData1> itrbl, Collector<MyData2> clctr) throws Exception {
int id = 0;
for (MyData1 myData1 : itrbl) {
clctr.collect(new MyData2(id++, myData1));
}
}
});
Any ideas how I could run this segment in parallel? Thanks in advance!

How do I timeout a method after fixed time in java using concurrency executor future?

Using java concurrent executor, future cancel method not stopping the current task.
I have followed this solution of timeout and stop processing of current task. But it doesn't stop the processing.
I am trying this with cron job. Every 30 seconds my cron job gets executed and I am putting 10 seconds timeout. Debug comes in future cancel method, but it is not stopping current task.
Thank you.
#Scheduled(cron = "*/30 * * * * *")
public boolean cronTest()
{
System.out.println("Inside cron - start ");
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
System.out.println(dateFormat.format(date));
System.out.println("Inside cron - end ");
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() {
int i=1;
while(i<100)
{
System.out.println("i: "+ i++);
try {
TimeUnit.SECONDS.sleep(1);
}
catch(Exception e)
{
}
}
return null;
}
};
Future<Object> future = executor.submit(task);
try {
Object result = future.get(10, TimeUnit.SECONDS);
} catch (Exception e)
} finally {
future.cancel(true);
return true;
}
}
The expected result is cron job runs every 30 seconds and after 10 seconds it should time out and wait for approximately 20 seconds for a cron job to start again. And should not continue the older loop because we have timeout on 10 seconds.
Current result is:
Inside cron - start
2019/07/25 11:09:00
Inside cron - end
i: 1
i: 2
i: 3
i: 4 ... upto i: 31
Inside cron - start
2019/07/25 11:09:30
Inside cron - end
i: 1
i: 32
i: 2
i: 3
i: 33
...
Expected result is:
Inside cron - start
2019/07/25 11:09:00
Inside cron - end
i: 1
i: 2
i: 3
i: 4 ... upto i: 10
Inside cron - start
2019/07/25 11:09:30
Inside cron - end
i: 1
i: 2
i: 3 ... upto i:10
The first problem is in this part of code:
catch(Exception e)
{
}
When you invoke future.cancel(true); your thread is being interrupted with Thread.interrupt()
Which means that when a thread is sleeping, it gets awoken and throws InterruptedException which is caught by the catch block and ignored. To fix this problem you have to handle this exception:
catch(InterruptedException e) {
break; //breaking from the loop
}
catch(Exception e)
{
}
The second problem: Thread.interrupt() may be invoked while the thread is not sleeping. In this case InterruptedException is not thrown. Instead, the interrupted flag of the thread is raised. What you have to do is to check for this flag from time to time, and if it's raised, handle interruption. The basic code for it would look like:
try {
if (Thread.currentThread().isInterrupted()) {
break;
}
TimeUnit.SECONDS.sleep(1);
}
...
// rest of the code
UPDATE:
Here's the full code of Callable:
Callable<Object> task = new Callable<Object>() {
public Object call() {
int i=1;
while(i<100)
{
System.out.println("i: "+ i++);
try {
if (Thread.currentThread().isInterrupted()) {
break; //breaking from the while loop
}
TimeUnit.SECONDS.sleep(1);
} catch(InterruptedException e) {
break; //breaking from the while loop
} catch(Exception e)
{
}
}
return null;
}
};

confusion in acquiring and releasing of locks

I have the following code snippet from Client of an Android emulator:
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,String sortOrder) {
String key = selection;
String keyHash = genHash(key);
Log.v("provider.query","Key & keyHash: "+key+" & "+keyHash);
if(SimpleDhtUtil.toForward(keyHash, currentHash, predecessorHash)){
DhtDto dto = new QueryTransfer(successorPort, currentPort, -1, key, keyHash);
st.makeSendRequest(dto);
synchronized(BigLock.LOCK){
SimpleDhtUtil.cursorReset();
requiredAnswers = 1;
currentAnswers = 0;
}
while(requiredAnswers>currentAnswers){
synchronized(BigLock.LOCK){
try{
if(requiredAnswers>currentAnswers){
Log.d("provider.externalQueryLock","CA: "+currentAnswers+"RA: "+requiredAnswers+" Waiting... "+BigLock.LOCK);
BigLock.LOCK.wait();
Log.d("provider.externalQueryLock","Woke up");
}
}catch(InterruptedException e){
Log.e("provider.query", "InterruptedException",e);
}
}
}
return SimpleDhtUtil.getCursor();
}
The following code in the Server of the same AVD:
private void acceptAnswer(QueryAcknowledge qa) {
// Object lock = SimpleDhtProvider.externalQueryLock;
synchronized(BigLock.LOCK){
SimpleDhtProvider.currentAnswers += 1;
Log.d("ReceiverTask.acceptAnswer","Got result. Current count: "+SimpleDhtProvider.currentAnswers);
SimpleDhtUtil.addValues(qa.getRecords());
Log.d("ReceiverTask.acceptAnswer","Aggregated result. Net count: "+SimpleDhtUtil.getCursor().getCount());
BigLock.LOCK.notifyAll();
Log.d("ReceiverTask.acceptAnswer","lock released: "+BigLock.LOCK);
}
}
Now the problem is that when releasing the lock in the server code, I want the lock in the client to be notified and awoken. This happens >80% of the time. But sometimes it gets stuck. Find the android log below. Also, the currentAnswers and requiredAnswers are always being handled from the client, i.e., these variables are static and volatile in Client and BigLock is an enum with only one value as LOCK.
Client log:
04-14 08:14:07.172: V/provider.query(2699): Key & keyHash: 6oLNUimWIuAM4YWN183cwtz0te5aq6r7 & 837cccd1cac03a9c4c9169fad595a997d2673920
04-14 08:14:07.202: D/provider.externalQueryLock(2699): CA: 0RA: 1 Waiting... LOCK
Server log:
04-14 08:14:07.192: D/ReceiverTask.acceptAnswer(2699): Got result. Current count: 2
04-14 08:14:07.192: D/ReceiverTask.acceptAnswer(2699): Aggregated result. Net count: 2
04-14 08:14:07.192: D/ReceiverTask.acceptAnswer(2699): lock released: LOCK
The problem here is that I was resetting the cursor after sending the request from the client assuming that the Server would receive reply after resetting the cursor in the next line.
The correct order is first reset the cursor and then send the request.

Cycle through imageview

I've got this code :
public void createTask() {
for (int i = 0; i < 6; i++) {
Random rnd = new Random();
int color = rnd.nextInt(10);
showImage(color);
}
But I want it to cycle through the image-views.. so show one, keep it on the screen for 3 seconds, then show 2nd, keep that on screen for 3 seconds, show 3rd and so on.
I've made showImage and hideImage methods to keep code clean :
public void showImage(int color) {
((ImageView) findViewById(myImagebtns[color]))
.setVisibility(View.VISIBLE);
};
How should I program the waiting time (sleep? thread?) not locking the UI?
To not block UI thread use a Handler with its postDelayed method.
int repeatCount = 0;
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
switchImage();
Log.d("MSG", "repeatCount is : " + repeatCount);
repeatCount ++;
if(repeatCount < 5) {
handler.postDelayed(this, 3000);
}
}
};
handler.postDelayed(runnable, 3000);
I suggest you to use a single ImageView and switch its background color or image resource every 3 seconds. (Using ImageViews for every image will be a cost for your app.)
public void switchImage() {
ImageView myImageView = (ImageView) findViewById(R.id.myImageView);
// TODO: get your image or color here and apply it to your single imageView
// You may need an index while getting the next image or randomly get it.
myImageView.setImageResource(getNextImageResId());
}
Edit: If you want to switch n times you can define a variable(such as repeatCount) and increment that variable. If you log out you'll see something like this(As you see every lines have 3 seconds difference):
11-11 20:17:19.909: D/MSG(1068): repeatCount is : 0
11-11 20:17:22.917: D/MSG(1068): repeatCount is : 1
11-11 20:17:25.921: D/MSG(1068): repeatCount is : 2
11-11 20:17:28.921: D/MSG(1068): repeatCount is : 3
11-11 20:17:31.925: D/MSG(1068): repeatCount is : 4

Categories

Resources