Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 9 years ago.
Improve this question
I am writing inside an activity.
I simply want to set a variable of this activity to true, wait 5 seconds and switch the variable back to false without freezing the current thread execution.
Any help is appreciated. I have googled this for hours and tried all sorts to no success.
I think what you are looking for is the AsyncTask.
http://developer.android.com/reference/android/os/AsyncTask.html
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);
You can do that starting a Thread. Example:
boolean myvar = true;
new Thread(
new Runnable() {
public void run() {
SystemClock.sleep(5000);
myvar = false;
}
}
}).start();
you need to implement the ASyncTask interface, and sleep inside the doInBackground() method and change your variable back in the onPostExecute() method
in your class you have you boolean variable
boolean bValue = false;
Then add a private class inside your Activity
private class sleepFiveTask extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
bValue = true;
}
protected void doInBackground(Void... params) {
try {
Thread.sleep(5000); //sleep for 5 seconds
} catch (InterruptedException e) {
e.printStackTrace();
// handle the exception...
// For example consider calling Thread.currentThread().interrupt(); here.
}
}
protected void onPostExecute(Void result) {
bValue = false;
}
}
and when you want to execute it run
new sleepFiveTask ().execute();
Related
I have this button that when clicked calls a thead to update user ui:
averageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new Testing().execute();
}
});
The method gets executed but it freezes the UI for 10 seconds. I want to update the UI everytime I call the averageMiles.append(mile) method.
class Testing extends AsyncTask<Void, Void, Void> {
#Override
protected void onPostExecute(Void unused) {
int x = 0;
while (true) {
if (x == 10) {
break;
}
ArrayList<Double> milesList = new ArrayList<>();
if (x == 0) {
averageMiles.setText("mph: ");
}
String mile = milesValue.getText().toString();
if (!isNum(mile)) {
continue;
}
averageMiles.append(mile);
milesList.add(Double.valueOf(mile.trim()));
x++;
if (x == 10) {
averageMiles.append("\nAverage: " + getAverage(milesList));
return ;
} else {
averageMiles.append(", ");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Use ThreadPool executor from official oracle and android developer documentations
Oracle Docs - java.util.concurrent.ThreadPoolExecutor
Android Docs - java.util.concurrent.ThreadPoolExecutor
as you have specified you are using java the above two documentation is recommended by google as show below for AsyncTask
This class was deprecated in API level 30.
Use the standard java.util.concurrent or Kotlin concurrency utilities instead.
The ultimate objective is the android is saying that, if you want to update UI, simply use runOnUiThread with a new runnable you update the UI, which means for each UI update you may be creating fresh short term thread which only updates the UI and thread finishes and garbage collected
Sample Code
public class MainActivity extends AppCompatActivity {
int count = 0;
Executor ex;
MyThread th;
class MyThread extends Thread implements Runnable {
private boolean running=false;
public void setRunning(boolean running) {
this.running = running;
}
#Override
public void run() {
while(running) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
#Override
public void run() {
count++;
TextView tv = findViewById(R.id.textView);
tv.setText(String.valueOf(count));
}
});
}
}
}
public void onStartClick(View view) {
th = new MyThread();
ex = Executors.newSingleThreadExecutor();
th.setRunning(true);
ex.execute(th);
}
public void onStopClick(View view) {
if(th!=null) {
th.setRunning(false);
}
}
}
all the member variables of the class should be only accessed inside runOnUiThread, for example count++ count is a variable of the MainActivity if you want any value specific to the thread you put only inside the MyThread class
Never try to access any of the MainActivity variable inside the run() method
You can also write MyThread as separate class, and set values similar to th.setRunning before starting the thread.
If you want a callback after the thread is completed use an interface which will give you a callback method in your MainActivity
So it is simply core java
I have created an example with interface
Concurrent Executor Interface Example
I am using Android Studio. I am trying to fix a clock in which I pressed the button, it will return the time to 12:00. I got it working but I want it to be executed by waiting 250 miliseconds. The problem is that they only wait for 250 miliseconds (but there are two executions so that's 5 seconds) and then it goes to 12:00 right away without showing it to the Text View. Is there something I am doing wrong? Also if I applied handler function here, I'm afraid I don't have much knowledge to use that.
Edit: This is from my MainActivity method. Example, change from 1 to 2 then wait for 250 miliseconds, change from 2 to 3 then wait for 250 miliseconds
synchronized (this){
try {
while(minuteHand != 0 || hourHand != 12){
if (hourHand != 12){
hourHand++;
hourText.setText(Integer.toString(hourHand));
wait(250);
}
if (minuteHand != 0) {
minuteHand += 5;
minuteHand %= 60;
minuteText.setText(Integer.toString(minuteHand));
wait(250);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Below is the proper way to update UI elements from an asynchronous thread:
public class SampleActivity extends Activity {
private TextView hourText;
private TextView minuteText;
private void updateHourText(final String text) {
runOnUiThread(new Runnable() {
#Override
public void run() {
hourText.setText(text);
}
});
}
private void updateMinuteText(final String text) {
runOnUiThread(new Runnable() {
#Override
public void run() {
minuteText.setText(text);
}
});
}
private class ClockTask extends AsyncTask<Void, Void, Void>
{
private int hourHand;
private int minuteHand;
public ClockTask(int hourHand, int minuteHand) {
this.hourHand = hourHand;
this.minuteHand = minuteHand;
}
#Override
protected Void doInBackground(Void... voids) {
try {
while(minuteHand != 0 || hourHand != 12){
if (hourHand != 12){
hourHand++;
updateHourText(Integer.toString(hourHand));
Thread.sleep(250);
}
if (minuteHand != 0) {
minuteHand += 5;
minuteHand %= 60;
updateMinuteText(Integer.toString(minuteHand));
Thread.sleep(250);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
}
And then call this from your button's onClickListener():
new ClockTask(hourHand, minuteHand).execute();
As you can see, in order to update TextView's text, a helper method was needed, which would always execute TextView.setText() inside your main thread. That way, your business logic can execute within its own thread (without causing main thread to wait, which would lead to unresponsive UI), while updating your TextViews asynchronously.
Also, you should never try to update UI elements outside your main thread's context as it will lead to an exception being thrown.
I'm trying to use jsoup to display temperature of Boston from a website as a toast message in an android app. My Java program looks like this:
public static void showWeather() throws IOException
{
Document doc = Jsoup.connect("http://www.wunderground.com/US/ma/boston.html?MR=1").get();
Elements languages = doc.select("#tempActual span.b ");
for(Element langElement: languages)
{
//System.out.println(" The temperature in Boston: "+langElement.text()+ " F");
}
}
The Java program works Okay and prints the temperature of Boston to the screen. I want to use this method to try to display the temperature as a toast in a simple android app, but when I try to run to method (without the print statement of course) in the onCreate method in my android activity, the program closes automatically. Here's my onCreate method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addKeyListener();
try {
showWeather();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Can anybody please tell how to run this java program in my android activity? I don't know how to treat the try/catch clause properly. I tried put toast in the catch clause but to no avail. Please help.
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.
Reference:
http://developer.android.com/reference/android/os/AsyncTask.html
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);
I'm making a word game for android, and basically whenever a user enters something right I'm updating the score in the application, and I want to show the score on the screen to make it show in big then fade out slowly and get smaller, how can I do that? and is it possible to implement it in an AsyncTask class?
This is the method I'm using to check if the word entered is right.
public class checkWord extends AsyncTask<String, String, Void> {
private String c;
#Override
protected Void doInBackground(String... arg0) {
int size = correctWords.size();
String word = arg0[0];
for (int i = 0; i < size; i++) {
if (word.equalsIgnoreCase(correctWords.get(i))) {
publishProgress("bad");
}
}
try {
c = bufferedReader.readLine();
while (c != null && !c.equalsIgnoreCase(word)) {
c = bufferedReader.readLine();
}
if (c != null) {
correctWords.add(0, word);
score += word.length();
publishProgress("good");
} else {
incorrectWords.add(0, word);
publishProgress("bad");
}
} catch (IOException e) {
e.printStackTrace();
}
closeWordFile();
openWordFile();
return null;
}
So is there anyway I could pass a param to the publishProgress so that in onProgressUpdate I draw the score they got, for example +3 then make it fade out?
This is my onProgressUpdate where I add seconds to the timer and play a sound if it's a valid word or not
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
if (values[0].matches("bad"))
failureSound.start();
if (values[0].matches("good")) {
successSound.start();
if (countDownTimer != null) {
countDownTimer.cancel();
startTimer(countDownTime + c.length() / 2);
}
}
}
Because of Single threaded model in Android, only main thread can update UI, You can try the same in
runOnUiThread(new Runnable()
{
public void run()
{}
}
method.
Instead use a toast message. It will not affect your UI.
I am very frustrated as I've been trying to implement a super simple loading wheel while waiting on a network call. I have searched and read dozens of SO questions and I just feel like I must be missing something, unless nobody really does what I'm trying to do. I have tried going down the AsyncTask route, but that's not what I want.
Let me also say that right now my app works perfectly, it's just that the transition from screen to screen appears to hang as it waits on the network. I just want a loading wheel so that in the 1-2 seconds the user knows the app is working and didn't freeze.
Here's what my current network call looks like:
private static String sendDataToServer(String arg1, String arg2)
{
Thread dbThread = new Thread()
{
public void run()
{
// do the call that takes a long time
}
};
dbThread.start();
try {
// I do this so that my program doesn't continue until
// the network call is done and I have received the information
// I need to render my next screen
dbThread.join();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
Now, why can't I just add the ProgressDialog like this? If I do this, the progressDialog never appears.
private static String sendDataToServer(String arg1, String arg2)
{
final ProgressDialog progress = new ProgressDialog(BaseActivity.getInstance());
progress.setIndeterminate(true);
progress.setMessage("Loading...");
progress.show();
Thread dbThread = new Thread()
{
public void run()
{
// do the call that takes a long time
}
};
dbThread.start();
try {
dbThread.join();
progress.dismiss();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
I think I'm stuck because the network call needs to be on a separate thread from the UI thread, yet I don't want to continue in my application because I need the results of that call to continue. But if I do thread.join() I hold up everything. I thought I needed AsyncTask but that went downhill quickly. Here's my question on that if you're curious.
Android's AsyncTask: multiple params, returning values, waiting
How the heck to I just show a loading dialog while this call happens without proceeding through the rest of my application?
EDIT
Here's my AsyncTask attempt.
private class PostToFile extends AsyncTask<PostToFile, Void, Void>{
private String functionName;
private ArrayList<NameValuePair> postKeyValuePairs;
private String result = "";
public PostToFile(String function, ArrayList<NameValuePair> keyValuePairs){
functionName= function;
postKeyValuePairs = keyValuePairs;
}
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(BaseActivity.getInstance(), "Loading", "Please wait...", true, false);
}
#Override
protected Void doInBackground(PostToFile... params) {
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair(FUNCTION_KEYWORD, functionName));
for (int i = 0; i < postKeyValuePairs.size(); i++) {
nameValuePairs.add(postKeyValuePairs.get(i));
}
try{
// ***do the POST magic.***
result = response.toString();
}
catch (Exception e){
// clean up my mess
}
return null;
}
private String getResult(){
return result; // can I use this somehow???
}
#Override
protected void onPostExecute(Void result) {
progressDialog.dismiss();
}
}
And when I use it:
new PostToPHP(FUNCTION_NAME, postPairings){
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try
{
if (result != null && !result.startsWith("null"))
{
JSONArray jArray = new JSONArray(result);
parseData(jArray);
}
}
catch (JSONException e)
{
Log.e(Constants.LOG_TAG, e.toString());
}
};
}.execute()
The problem is, I have a couple of these calls back to back, and they're each dependent on each other. So the first one starts, and the second one starts immediately after the first one starts, but before the first one is finished. So I get erroneous behavior. How can I start the second call only after the first is completely done?
Maybe this will work, I haven't tested, but you can try:
public class MyTask extends AsyncTask<String, Void, String> {
private int flag;
public MyTask(int flag) {
this.flag = flag;
}
#Override
protected String doInBackground(String... params) {
switch (flag) {
case 1:
return doNetworking1();
break;
case 2:
return doNetworking2();
break;
case 3:
return doNetworking3();
break;
default:
return doNetworking1();
}
}
#Override
protected void onPreExecute() {
//show progress dialog
}
#Override
protected void onPostExecute(String s) {
//hide progress dialog
switch (flag) {
case 1: //do something with result
new MyTask(2).execute();
break;
case 2: //do other stuff
new MyTask(3).execute();
break;
case 3: //do event more stuff
break;
default:
//do something
}
}
}
and usage:
new MyTask(1).execute();
In cases of network connections I would use IntentService instead of AsyncTask.
For example create IntentServices for network connection:
public class NetworkCallIntentService extends IntentService {
public static final String BROADCAST_ACTION = "com.yourpackage:NETWORK_CALL_BROADCAST";
public static final String RESULT = "com.yourpackage:NETWORK_CALL_RESULT";
public NetworkCallIntentService() {
super(NetworkCallIntentService.class.getSimpleName());
}
#Override
protected void onHandleIntent(Intent intent) {
// get data from intent if needed
// do the call that takes long time
// send broadcast when done
Intent intent = new Intent(BROADCAST_ACTION);
intent.putExtra(RESULT, "some_result");//and more results
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
Next, start that service from activity, show progress dialog and move code responsible for showing next screen to BroadcastReceiver#onReceive() method:
public class SomeActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//start service
Intent serviceIntent = new Intent(this, NetworkCallIntentService.class);
//put extras into intent if needed
//serviceIntent.putExtra("some_key", "some_string_value");
startService(serviceIntent);
//here just show progress bar/progress dialog
}
#Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mNetworkCallReceiver,
new IntentFilter(NetworkCallIntentService.BROADCAST_ACTION));
}
#Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mNetworkCallReceiver);
}
private BroadcastReceiver mNetworkCallReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//hide progress bar/progress dialog
//here get results from intent extras
String result = intent.getStringExtra(NetworkCallIntentService.RESULT);
//process results and continue program(go to next screen, show error message etc.)
}
}
}
Declare service in manifest file:
<service
android:name="com.yourpackage.DownloadSvtValuesIntentService"
android:exported="false" >
</service>