I have got some problems to understand runOnUiThread(). I want to update the TextView continously but nothing happens. The GUI is still blocked. Could somebody help me?
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
runner();
}
public void runner (){
String[] testFiles = GeneralHelper.getPictureFileList();
TextView text = (TextView) findViewById(R.id.textfeld);
for (int i = 0; i < 2; i++)
{
runOnUiThread(new Runnable() {
public void run() {
text.setText("\n" + GeneralHelper.getPictureFileList()[i]);
}
});
...
// image analysis
}}
The loop has only 2 iterations and it is done so fast that you even can't see changes. You only see result GeneralHelper.getPictureFileList()[1]
And you are inside UiThread so you shouldn't use it. Just:
public void runner (){
String[] testFiles = GeneralHelper.getPictureFileList();
TextView text = (TextView) findViewById(R.id.textfeld);
for (int i = 0; i < 2; i++)
{
text.setText("\n" + GeneralHelper.getPictureFileList()[i]);
}
}
Sounds like you need to create your own timer class where you can include runOnUiThread() to update your TextView. That's what I did on a program I wrote where I needed to display the time counting up every second as soon as the user pressed a button.
Related
Android. I am trying to set background colour at time to make some sort of trainer. But this loop set background colour for all 4 LivearLayouts at ONE TIME - after the last iteration. And i need to do it one by one with pauses. How can i do it?
private LinearLayout[] lls;
lls = new LinearLayout[4];
lls[0] = findViewById(R.id.ll01);
lls[1] = findViewById(R.id.ll02);
lls[2] = findViewById(R.id.ll03);
lls[3] = findViewById(R.id.ll04);
public void onClick(View view) throws InterruptedException {
for (int i = 0; i < 4; i++) {
Thread.sleep(3000);
lls[i].setBackgroundColor(Color.parseColor("red"));
}
}
Such a code changes colour for all 4 objects at once - after the end of the 4th iteration. Prior to this, the colour of none has changed.
I think you should use a handler instead of for loop. Handlers are more convenient for delaying and doing some stuff. I am putting some edited code for you.
private LinearLayout[] lls;
private Long timeInMillis = 3000L;
private Handler handler;
private Runnable runnable;
private int index = 0;
private void setColors(){
lls = new LinearLayout[4];
lls[0] = findViewById(R.id.ll01);
lls[1] = findViewById(R.id.ll02);
lls[2] = findViewById(R.id.ll03);
lls[3] = findViewById(R.id.ll04);
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
if(index!=lls.length){
lls[index++].setBackgroundColor(Color.parseColor("red"));
handler.postDelayed(runnable,timeInMillis);
}
}
};
handler.postDelayed(runnable,timeInMillis);
}
It was wrong code. You cant change smth in activity in one thread. It was solved by adding thread with loop that sends Broadcast messages for BroadcastReciever in MainActivity.
I am making a piano app in which I need to emulate pressing keys in order to show the user the notes of a song. By using a handler, I am able to make a delay pressing up and down a key.
However, I am not able to make a delay between all the keys which have to be touched. I thought something like this, but I only see the last 2 notes get pressed and sound.
final String[] keys = {"1b","2w","9b","10w","11b","12w"};
handler = new Handler(Looper.getMainLooper());
for(int i = 0; i < keys.length - 1; i++) {
final int nextKey = i+1;
//Method in which I used other handler to delay pressing up and down
pressKey(keys[i]);
//Next key i would like to get pressed with a delay
handler.postDelayed(new Runnable() {
#Override
public void run() {
pressKey(keys[nextKey]);
}
},1500);
}
Instead of using for, use a runnable that will keep posting itself with the specified delay:
new Runnable()
{
int nextKey = 0;
#Override
public void run()
{
pressKey(keys[nextKey]);
if (++nextKey < keys.length)
handler.postDelayed(this, 1500);
// else no more keys
}
}.run();
I feel kinda stupid after all the night trying to figure it out. I just had to make a variable with the delay, and increment it in each iteration.
You can do this with a thread if in pressKey method there is no work that needs to be done in the UI thread.
new Thread(
new Runnable(){
#Override
public void run(){
for(int i = 0; i < keys.length - 1; i++) {
pressKey(keys[i]);
Thread.sleep(1500);
}
}
}
).run();
I'm trying to make a repeating loop to display increasing numbers in a single textview.
The general idea is this
....
int rep = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.Layout);
do { meth(); } while (rep < 11);
}
private void meth() {
final TextView textv = (TextView) findViewById( R.id.tex );
String srep = Integer.toString(rep);
textv.setText(srep);
if(rep <11) { rep = rep +1; }
}
....
The idea is to display the numbers 1 to 10 in the textview textv ONE BY ONE on screen. But when I ran it, it just shows 10. I'm tried to put in a CountDownTimer inside meth() and also inside the do {} loop but it just crashes the program.
Would appreciate if anyone can point me the right way of doing this.
Try this
private class MethTask extends AsyncTask<String, String, String> {
protected String doInBackground(String... urls) {
do { meth(); SystemClock.sleep(1000);
} while (rep < 11);
return "";
}
}
And call from onCreate() like this:
new MethTask().execute("");
First thing you cannot run this code into oncreate otherwise you won't see anything since onCreate is run before the activity is rendered.
So what you should do is first create a CountownTimer, start it in the onStart method this way:
handler.postDelayed(new Runnable() {
startCountDown();
}, 1000);
This way you will be sure the activity is displayed
UPDATE
If you use CountownTimer there is no need to call sleep or other similar methods
could anyone explain, what i'm doing wrong?
in this case below, "tt" is my TexView.
On my Oncreate() method, I have:
tt = (TextView) findViewById(R.id.ni);
tt.setText("This is a try");
and then
tt.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
String vi = tt.getText().toString().substring(tt.getSelectionStart(),tt.getSelectionEnd());
Toast.makeText(getApplicationContext(), vi,Toast.LENGTH_LONG).show();
}
});
Nothing is Shown at Onclick.
thanks.
I encountered the same problem a few days ago and I could find the following solution in the end. Delaying the process even 10 milliseconds could help interestingly. Put this in your onClick/onLongClick method, wherever you want to fetch the selected text.
For the original answer: textView.getSelectionEnd() returning start index value on Samsung Marshmallow 6.0 devices
I hope this helps those who have similar problem in the future.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
int startIndex = textView.getSelectionStart();
int endIndex = textView.getSelectionEnd();
if ((endIndex - startIndex) <= 0) {
return;
}
// UI related code here
}
}, TIME_IN_MS_TO_DELAY);
return false;
I'm very new to Android. I've used Java before but not for around a year and a half. I'm having problems getting the screen to update, or rather the TextView. I have looked around the net for hours for solutions and I sort of know why its not working, but I don't know how to fix it.
public class PreliminaryActivity extends Activity {
//private static final int MENU_QUIT = Menu.FIRST;
int i = 0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getWindow().setBackgroundDrawableResource(R.drawable.background);
mainComputations();
}
public void mainComputations(){
runOnUiThread(new Runnable(){
//#Override
public void run(){
TextView tv = (TextView) findViewById(R.id.time_display);
tv.setText(new Integer(i).toString());
i++;
}
});
}
I've cut my program down so it should just increment an int value on the screen for testing and it still will not work. Instead it just displays '0'. If I add a for loop before the runOnUiThread() method, it will increment the i value but I have a feeling it is simply increasing the value then displaying it rather than it updating in real time. Any help would be greatly appreciated.
Go for TextSwitcher
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/TextSwitcher1.html
If you want your textview to update with some delay.
use something like this.
final int length = 10;
Thread t = new Thread(new Runnable() {
#Override
public void run() {
for(int i=0 ; i<length; i++) {
runOnUiThread(new Runnable() {
#Override
public void run() {
tv.setText(new Integer(i).toString());
}
}) ;
i++;
Thread.sleep(500);
}
}
});
t.start();
In android, You can not update the UI from another thread. This is the restriction (which I consider a feature to remove unncecessary bugs) in android development. You can use AsyncTask for this...
In use, you can perform long task inside donInBackground() and than UI can be updated using onProgressUpdate()... see the AsyncTask example here
EDIT
see this similar question for more information...
Your problem is because you call the mainComputations() only once. You should take a look at AsyncTask and the Android Developer resource Updating the UI from a Timer
You can not Update Main UI Thread from another thread for that you need to use Handler. Refer this link for more details
http://www.vogella.com/articles/AndroidPerformance/article.html
What I see is that you call mainComputations only one time, so it is 0.