after some time of programming I decided to download the Android SDK and see if I should start focusing on mobile development to start making money.
At the moment I am just trying to get used to how the android works and up until now I have a basic understanding of the events and the way the xml files interact with the .java files.
To learn I'm just trying to do tests of basic stuff and now I have something like this :
TextView text = (TextView)findViewById(R.id.lol);
number mnumber = new number();
mnumber.change_in_number();
text.setText(mnumber.get_in_number() + "");
Let me explain;
number is a class I make which has an integer varibale inside, a function to get the value (get_in_number) and a function to change the integer variable to a random value (change_in_number).
All of this functions work es intended for they are very simple but when I run the code this only happens once (as expected).
My question now is...
Exactly how would I make this code repeat itself every X amount of seconds?
You know, to have the value changed multiple times without the need of any event while the application is running.
I know this question is really simple and probably also easy to answer but right now I really need help with getting started.
Thanks in advance for your help.
This might be a lot over your head but you need to create a separate thread with a while loop to periodically update your TextView. I didn't compile and run this but it should be pretty close to exactly what you want:
public class YourActivity extends Activity
{
private UpdaterThread updaterThread;
private Runnable changeNumberRunnable;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
changeNumberRunnable=new Runnable()
{
#Override
public void run()
{
YourActivity.this.updateNumber();
}
};
}
#Override
protected void onResume()
{
super.onResume();
updaterThread=new UpdaterThread();
updaterThread.start();
}
#Override
protected void onPause()
{
super.onPause();
updaterThread.kill();
}
private void updateNumber()
{
TextView text = (TextView)findViewById(R.id.lol);
number mnumber = new number();
mnumber.change_in_number();
text.setText(mnumber.get_in_number() + "");
}
private class UpdaterThread extends Thread
{
private boolean running;
public void kill()
{
running=false;
}
#Override
public void run()
{
running=true;
while(running)
{
//you can't change a view from a separate thread, so call the update on the main UI thread
YourActivity.this.runOnUiThread(changeNumberRunnable);
//sleep for 5 seconds, if we're interrupted then exit the loop
try { Thread.sleep(5000); }
catch(InterruptedException e) { running=false; }
}
}
}
}
Related
So as the title probably suggests - I've done a lot of research on the topic, but I am still confused and unable of achieving what I want.
In very simplified scenario, I have a LoginActivity in which is method boolean validateUserInput(String mail, String password) and I want to do the check input in the separate thread. I suppose I will extend it in the future to do the log-in itself as well (http request). Naturally I would like to get boolean value if the operation was successful or not - and in the process of operation I want to show progressbar dialog.
Make a thread, run the code, return its result, show the progress bar in a meantime, piece of cake right?
Should I use asynctask or runnable? How do I do this so I do not block the UI thread?
This is code I tried to use in LoginActivity:
new Thread(new Runnable() {
#Override
public void run() {
mUserInputValidated = validateUserInput(inputEmail.getText().toString(), inputPassword.getText().toString());
}
}).start();
if(mUserInputValidated)
{
attemptUserLogin(inputEmail.getText().toString(), inputPassword.getText().toString());
}
I also tried asynctask approach, but ended up with various errors since I started progress dialog in onPreExecute() and ended it in onPostExecute(), using reference like LoginActivity.this where was the problem with memory leak which I was also unable to fix?
I assume this is pretty usual scenarios, since almost every app use it, so - what are common approaches? How do I fix my code?
You have to use asynctask this will take the work off from main-thread and place it on background thread once the work is done
This is a sample that shows how to do it
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
return "Executed";
}
#Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed"); // txt.setText(result);
// might want to change "executed" for the returned string passed
// into onPostExecute() but that is upto you
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
Reference
When I show an alertdialog, I start a thread that starts a 30 second countdown to update a determinate progressbar shown in this alertdialog.
I create the runnable as a static inner class so that I don't leak the context(activity), but then of course I can't access the flag to stop the thread, nor the views I want to update. How can I get around this?
public class MyDialogFragment implements DialogInterface.onShowListener, DialogInterface.onDismissListener {
private boolean stopThread = false;
private Progressbar countdownBar;
private TextView countdownRatio;
#Override public void onShow() {
Thread progressThread = new Thread(new myRunnable());
progressThread.start();
}
#Override public void onDismiss() {
stopThread = true;
this.dismiss();
}
private static class myRunnable implements Runnable {
int progressStatus = 0;
int numSeconds = 30;
#Override public void run() {
while (!threadStop && progressStatus < numSeconds) {
progressStatus++;
handler.post(new Runnable() {
public void run() {
countdownBar.setProgress(progressStatus);
countdownRatio.setText(progressStatus + "/" + numSeconds + " secs");
}
});
try {
// update the counter every sec
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
First - don't use Thread - you're asking for troubles, especially that you don't seem to be comfortable with multi-threaded programming. It's a tricky topic with tons of pitfalls. It's definitely not for noobs.
You may use AsyncTask for this - it has nice integration with UI event loop via AsyncTask.onProgressUpdate(). AsyncTask uses internal thread pool.
http://developer.android.com/guide/components/processes-and-threads.html#Threads
AsyncTask is ok for most trivial stuff. For more advanced uses try using Service with worker threads and message bus to communicate with fragments or activities. There is plenty of libraries for asynchronous programming. I can recommend this one:
https://github.com/stephanenicolas/robospice
It's main purpose if networking, but you can use it for other stuff as well.
Third solution is Loader API:
http://developer.android.com/reference/android/content/Loader.html
It's intended for asynchronous loading of data from database (SQLite is slow), but it's quite easy to use it for other stuff, such as data processing.
Remember: if you use Thread, there are 2 possibilities:
You are expert and you know what you're doing
You are green and you're doing it wrong
I'm new to Java and Android programming and taking a course on this via Coursera. My app has two images that animate up and down. Right now, I've gotten as far as having both images animate together repeatedly. I got help and wrote a recursive method to have them animate repeatedly until a pleaseStop boolean flag is changed.
I would like them to move independently. Rather than writing two stepRecursive methods, how can I write just one?
Here's where I set up and run the animation.
mHandler = new Handler(); // .os package class when importing
mLeftfoot = findViewById(R.id.leftfoot);
mRightfoot = findViewById(R.id.rightfoot);
mFootAnim = AnimationUtils.loadAnimation(this, R.anim.foot); //this looks to the foot.xml file for the animations
stepRecursive();
Here's my recursive method. Notice mInterval. I would like mLeftfoot and mRightfoot to run at their own mInterval.
private void stepRecursive() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mLeftfoot.startAnimation(mFootAnim);
mRightfoot.startAnimation(mFootAnim);
if (!pleaseStop)
stepRecursive();
}
}, mInterval);
Pass one boolean variable via stepRecursive() method and decide which View has to be animated based on that boolean value...
private void stepRecursive(final boolean isLeftFoot,final int mInterval) {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if (isLeftFoot) {
mLeftfoot.startAnimation(mFootAnim);
} else {
mRightfoot.startAnimation(mFootAnim);
}
if (!pleaseStop)
stepRecursive(isLeftFoot,mInterval);
}
}, mInterval);
}
and when calling this method, pass appropriate interval based on the boolean value.
like
stepRecursive(true,intervalForLeft);
stepRecursive(false,intervalForRight);
#first Sorry for my bad english.
I have created a own Listener. I want to change a TextView, when the Listener is called in the MainActivity from a Service. The idea for my own Listener is from:
http://tseng-blog.nge-web.net/blog/2009/02/17/how-implement-your-own-listener-android-java/
In the Code Example the TriggerMethod() ist called from a Calculation Thread, running in the Service.
I solved the Problem, but I find, it isn't pretty nice, because in every new Activity I have to make a new Thread. Is it possible to create an interface/listener that automatically can change the UI?
Used to solve the Problem:
http://developer.android.com/guide/components/processes-and-threads.html
ResultListener.java:
public interface ResultListener {
public void onResultAvailable(double result);
}
SimuService.java:
public class SimuService extends Service {
private ResultListener mResultListener = null;
public void setResultListener(ResultListener listener){
mResultListener=listener;
}
public void triggerMethode(){
observeResultDouble=getObserveDouble;
mResultListener.onResultAvailable(observeResultDouble);
}
MainActivity:
public class MainActivity extends FragmentActivity{
TextView txtView;
ResultListener mResultListener;
SimuService mSimuService;
protected void onCreate(Bundle savedInstanceState) {
txtView = (TextView) findViewById(R.id.txtServiceTime);
//Create Service .....an Bind
mResultListener = new ResultListener() {
#Override
public void onResultAvailable(double result) {
txtView.setText("Result: "+result);
}
};
mSimuService.setResultListener(mResultListener);
}
MY SOLUTION:
ResultListener = new ResultListener() {
#Override
public void onResultAvailable(double result) {
this.result=result;
runOnUiThread(setNewDataToUI);
}
};
private Thread setNewDataToUI = new Thread(new Runnable() {
#Override
public void run() {
txtView.setText("Result: "+result);
}
});
First of all: If you reference a Service in an Activity, the Service becomes pretty much useless. The advantage of services are, that they are loose coupled and can work indepenendtly form activities (=what the user sees) and its lifecycle and might even be in their own process. Thus activity-service communication is through intents or inter-process language AIDL, not through callbacks. If you want something executed asynchronosly use AsyncTask.
To your main problem: as you found out, you can only modify the UI on the UI-thread. So by design, leave changing UI in the component, thats responsibly for that (either activtiy or fragment), that will prevent the need of runOnUiThread()
Your code seems like txtView.setText("Result: "+result); will be executed in the Activity, but it wont. It will be executed in the Service, which (as I impleied before) does not run on the UI-thread. The problem is, I dont get the intent, what exactly you want to achieve so it is hard to give you an alternative solution.
I have a bunch of Buttons (custom, with a few extra methods to apply other backgrounds, and revert to original), which can be assigned a background. But since I don't know how large these backgrounds will or can be, I decided to set the background in a separate Thread. First, I had this code:
public void updateButton(final Button b, final String d, final String s) {
b.nullify(); //Recycles previous background, else OOM error
b.setText(s);
if (d != null) {
new Thread() {
#Override
public void run() {
b.setBackgroundFromBase64(d);
}
}.run();
}
else b.setBackgroundToDefault(); //Sets standard android background
}
but I soon found out that this wasn't the way to go. Slowly, the memory got flooded when I called this method a few thousand times. When I removed the new Thread() part, the memory wasn't flooded, so the Thread was the cause of this (Memory Analyzer Tool told me the same).
Then I tried the AsyncTask:
private class UpdateButtonTask extends AsyncTask<Object, Void, Void> {
#Override
protected Void doInBackground(Object... objs) {
String s = (String)objs[0];
Button b = (Button)objs[1];
String d = (String) objs[2];
b.nullify(); //Recycles previous background, else OOM error
b.setText(s);
if (d != null) b.setBackgroundFromBase64(d);
else b.setBackgroundToDefault();
return null;
}
#Override
protected void onProgressUpdate(Void v) {
//As far as I know, I don't need this method
}
#Override
protected void onPostExecute(Void v) {
//Neither this one
}
}
and call
new UpdateButtonTask().execute("Button", myButton, base64String);
in the button update method. But that didn't work either (the button wasn't updated at all. No text, no custom background). I read some articles and questions about Threading (this, this, and this amongst others), but I can't seem to get it working. For now, no Thread and hoping the phones are fast enough to not cause trouble on the UI thread seems to be the best option, but I'd rather have something more reliable, like a Thread.
What am I doing wrong? or maybe just the full question How can I update a Button background on a background Thread (so the UI doesn't stop working when applying larger backgrounds)?
I'm guessing that the problem is that you're trying to update the UI on a non-UI thread. This throws an exception and kills your AsyncTask.
You should separate the processing-intensive tasks to the AsyncTask and then apply UI changes on the main thread (using runOnUiThread(Runnable)).
Since you're using a custom button, I don't really know what you're not allowed to do on a non-UI thread. I'm guessing the setText function is causing problems, if you haven't overridden it.
You should start by wrapping the whole body of your doInBackground method in a try/catch block and logging the exception to isolate the problem.
May be this code will help you
new Thread(new Runnable() {
public void run() {
context.runOnUiThread(new Runnable() {
public void run() {
b.setBackgroundFromBase64(d);
}
});
}
}).start();