In my android application I am trying to show a "Loading..." text which will change every 100 ms. After every 100 milliseconds it will increase one dot. So first it will be like "Loading." and the after another 100 ms it will be "Loading.." When it will be "Loading..." , this process will terminate and again start from the first on words. It will continue till 3500 ms. It will be pretty like progress bar.
I hope I am able to explain the problem.
How to resolve this problem? Please help.
Not the best answer, but it works.
Handler handler = new Handler();
for (int i = 100; i <= 3500; i=i+100) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
if(i%300 == 0){
textView.setText("Loading.");
}else if(i%200 == 0){
textView.setText("Loading..");
}else if(i%100 == 0){
textView.setText("Loading...");
}
}
}, i);
}
Kotlin Snippet for Animating (Loading...):
ValueAnimator.ofInt(0, 4).apply {
repeatCount = 10
duration = 1000
addUpdateListener { valueAnimator ->
val dotsCount = valueAnimator.getAnimatedValue() as Int
if (dotsCount < 4) {
spannable.setSpan(transparentColorSpan, 7 + dotsCount, 10,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
textView.invalidate()
}
}
}.start()
A CountdownTimer seems to fit, change the text in onTick.
You should use an AsyncTask. This class is meant to do long-running background tasks that will publish updates and run on the UI thread automatically.
In doInBackground, have your loop that will then call publishProgress which will call onProgressUpdate every 100ms with the new values.
This will be done in the background and onProgressUpdate will run on the UI thread for you automatically.
Something on the lines of:
private class ShowLoading extends AsyncTask<Void, Integer, Void> {
#Override
protected Void doInBackground(Void... params) {
for (int i = 0; i < 3500; i++){
publishProgress(i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
if (values[0]%3 == 0){
textview.setText ("Loading.");
} else if (values[0]%3 == 1){
textview.setText ("Loading..");
} else if (values[0]%3 == 2){
textview.setText ("Loading..");
}
}
}
Related
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.
I am practicing the working of the AsyncTask and with that purpose I wanted to use the onProgressUpdate function. Currently in my program I have UI that lets the user choose an input (which would be show in a TextView after the AsyncTask is finished) and a timer (determines Thread.sleep() time in the AsyncTask)
What I want to do is ... if the user selects a time of 5. Then in every passing second I would like to send a notification to the UI (where a progress dialog is called) ... indicating progress of 1 of 5 ... 2 of 5 ... 3 of 5.
Here's the progress that I have made so far:
public class ViewFiller extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... input) {
// TODO Auto-generated method stub
try {
int time;
if (input[1].equalsIgnoreCase("")) {
time = 0;
} else {
time = Integer.parseInt(input[1]) * 1000;
for (int i = 1; i <= time / 1000; i++) {
publishProgress(i, time);
}
Thread.sleep(time);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return input[0];
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
execute.setText("Execute");
progress.dismiss();
tvInput.setText(result);
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
execute.setText("Running...");
displayProgress("Updating field ... ");
// Start the progress dialog
progress.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
progress.setMessage("Updating field ... " + values[0] + " of "
+ values[1] / 1000);
}
}
The current implementation only gives me 5 of 5 directly. Can anyone suggest me a solution ?
Because it is going through your loop faster than you see it
for (int i = 1; i <= time / 1000; i++) {
publishProgress(i, time);
You don't need the loop there. Just sleep for whatever amount of time then show your progress and have the sleep() and the publishProgress() in the loop. Something like
try {
int time = 0;
for (int i = 1; i <= time / 1000; i++) {
if (input[1].equalsIgnoreCase("")) {
time = 0;
} else {
time = Integer.parseInt(input[1]) * 1000;
publishProgress(time);
}
Thread.sleep(time);
}
Although, I'm not sure what input actually contains but you might want input[i]. It looks like its always going to be the same otherwise.
Also, CountDownTimer would be good for this I would think.
Can I use a thread for increment a counter and shows it in a frame of Android activity.
Public class MainActivity extendsActivity {
TextView counter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
counter = (TextView) findViewById(R.id.TV_counter);
Thread t = new Thread() {
public void run() {
runOnUiThread(new Runnable() {
public void run() {
for (int i = 0; i < 5; i++) {
try {
counter.setText("" + i);
System.out.println("Value of i= " + i);
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
};
t.start();
}
}
I wrote this code, but it run properly in console, but the text view displays i=4 in the terminal, I modified the time to sleep(3000) and the problem persists.
First you don't ever want to put sleep in UI Thread that can lead to unresponsive user interface and that is never good. You should use it just to update your graphics. Try replacing your code with this
Thread t = new Thread() {
public void run() {
for (int i = 0; i < 5; i++) {
try {
final int a = i;
runOnUiThread(new Runnable() {
public void run() {
counter.setText("" + a);
}
});
System.out.println("Value of i= " + i);
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
You are going to notice that sleep and for loop is outside UIThread and in your first thread, so basically all of your math is done outside and you just display the results.
This is just a correction of your code and suggestion for further thinking
EDIT: And for you to better understand why your code is not working, you set some value on your TextView, and immediately after you set UIThread to sleep, UIThread blocks instead of giving it time to finish updating graphics, after he finish sleep you set new value, and he never got to update previous one so in the end you see just the last one.
Hope this helps and enjoy your work.
you can use a CountDownTimer, and update your UI in the onTick() method ( this method is executed on the UI Thread):
int i=0;
CountDownTimer timer = new CountDownTimer(5000,1000) {
#Override
public void onTick(long millisUntilFinished) {
// this method will be executed every second ( 1000 ms : the second parameter in the CountDownTimer constructor)
i++;
txt.setText(i);
}
#Override
public void onFinish() {
// TODO Auto-generated method stub
}
};
timer.start();
I have created a program in android for multithreading.
When I hit one of the button its thread starts and print value to EditText now I want to determine that thread is running or not so that I can stop the thread on click if it is running and start a new thread if it is not running here is mu code:
public void startProgress(View view) {
final String v;
if(view == b1)
{
v = "b1";
}
else
{
v = "b2";
}
// Do something long
Runnable runnable = new Runnable() {
#Override
public void run() {
//for (int i = 0; i <= 10; i++) {
while(true){
if(v.equals("b1"))
{
i++;
}
else if(v.equals("b2"))
{
j++;
}
try {
if(v.equals("b1"))
{
Thread.sleep(3000);
}
else if(v.equals("b2"))
{
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
// progress.setProgress(value);
if(v.equals("b1"))
{
String strValue = ""+i;
t1.setText(strValue);
}
else
{
String strValue = ""+j;
t2.setText(strValue);
}
//t1.setText(value);
}
});
}
}
};
new Thread(runnable).start();
}
#Override
public void onClick(View v) {
if(v == b1)
{
startProgress(b1);
}
else if(v == b2)
{
startProgress(b2);
}
}
Instead of that messy code, an AsyncTask would do the job you need with added readability ...
It even has a getStatus() function to tell you if it is still running.
You'll find tons of examples by looking around a bit (not gonna write one more here). I'll simply copy the one from the documentation linked above:
Usage
AsyncTask must be subclassed to be used. The subclass will override at least one method (doInBackground(Params...)), and most often will override a second one (onPostExecute(Result).)
Here is an example of subclassing:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Once created, a task is executed very simply:
new DownloadFilesTask().execute(url1, url2, url3);
Use a static AtomicBoolean in your thread and flip its value accordingly. If the value of the boolean is true, your thread is already running. Exit the thread if it is true. Before exiting the thread set the value back to false.
There are some way can check the Thread properties
You able to check Thread is Alive() by
Thread.isAlive() method it return boolean.
You able to found runing thread run by
Thread.currentThread().getName()
Thanks
I am facing a very silly problem in my project and not able to resolve it. I am using AsyncTask for fetching current location of user. In that i used one counter to work as timer. Inside doInBackground I am incrementing that counter and if its greater than x value then i cancel the async task.
Here is the code snippet : -
class CurrentPositionTask extends AsyncTask<String, Void, Void> {
long counter = 0;
boolean flag = true;
#Override
public void onPreExecute() {
// TODO Auto-generated method stub
}
#Override
public Void doInBackground(String... params) {
// TODO Auto-generated method stub
do {
counter++;
if (latitude != 0 && longitude != 0) {
flag = false;
}
} while (counter <= 100000);
return null;
}
#Override
public void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
But here the while condition is not working. I also tried the for loop instead of while but that is not also working for me. Also face very strange problem, when i print the counter using sysout its working fine but without it its not working..
All suggestions are welcome.
This loop
while (counter <= 100000 || flag);
will go on as long as any of the conditions hold, so it will continue while counter <= 10000 or flag is true. If flag is false but counter is less than 100000 it will continue. If you intend to terminate the loop when flag is false, then you need to do instead:
while (counter <= 100000 && flag);
Update: It seems from your comments that you expect the hundred thousand incrementation of the counter variable to take roughly 20-30 seconds. Current day processors are way faster than that. I won't even mention the speed variation between processors, because its negligible anyway. You can wait for real 30 seconds with this loop, though is a busy-waiting loop (just like your original intent) and not something nice to do:
final long startTime = System.currentTimeMillis();
do {
...
} while( System.currentTimeMillis() - startTime <= 30 * 1000 );
Time bound task can be done using the TimerTask. Check the following:
boolean timeExpired = false;
#Override
protected Void doInBackground(Void... params) {
Timer t =new Timer();
TimerTask tk = new TimerTask() {
#Override
public void run() {
timeExpired = true;
}
};
t.schedule(tk, 500);
while(!timeExpired){
if (latitude != 0 && longitude != 0) {
t.cancel();
tk.cancel();
break;
}
}
return null;
}
Hope this helps.
Just use
Looper.prepare();
before while loop in doInBackground method