How to stop Executors.newSingleThreadScheduledExecutor(); in between the thread execution? - android

Below I am posting my code for the thread I am running to animate text in a RelativeLayout on top of the Page Curl activity by harism.
public void startProgress(final int index)
{
runnable = new Runnable()
{
#Override
public void run()
{
mArrWords.removeAll(mArrWords);
mStart.removeAll(mStart);
mEnd.removeAll(mEnd);
words = sentence.split(" ");
for(int i = 0; i < words.length; i++)
{
mArrWords.add(words[i]);
if(i == 0)
{
mStart.add(0);
mEnd.add(words[0].length());
}
else
{
mStart.add(mEnd.get(i-1)+1);
mEnd.add(mStart.get(i)+words[i].length());
}
/*Log.e("words", "" + "" + words[i]);
Log.e("mArrWords", "" + mArrWords);
Log.e("mStart", "" + mStart);
Log.e("mEnd", "" + mEnd);*/
}
for (int i = 0; i < mArrWords.size(); i++)
{
final int value = i;
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
mHandler.post(new Runnable()
{
#Override
public void run()
{
currIndex = index;
try
{
if(CurlView.ANIMATE)
tv1.setVisibility(View.VISIBLE);
else
tv1.setVisibility(View.GONE);
final Pattern p = Pattern.compile(mArrWords.get(value));
final Matcher matcher = p.matcher(sentence);
SpannableString spannableTxt = new SpannableString(sentence);
ForegroundColorSpan span = new ForegroundColorSpan(Color.RED);
while(matcher.find())
spannableTxt.setSpan(span, mStart.get(value), mEnd.get(value), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv1.setText(spannableTxt);
mHandler.sendEmptyMessage(0);
}
catch (Exception e)
{
e.printStackTrace();
mHandler.sendEmptyMessage(0);
}
}
});
}
}
};
final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
worker.schedule(runnable, CurlView.ANIMTIME+50, TimeUnit.MILLISECONDS);
}
Here, I am animating the text over images. I need to change the text for each page I am changing. I am able to change the text, however, when I turn the page, the index values I store in ArrayLists are not getting cleared. I am storing a sentence in an ArrayList named mArrWords and the indexes to refer to each word of sentence are stored in mStart and mEnd.
The problem I am facing is when the text changes, the animation starts with the previous indexes stored in mStart and mEnd ArrayLists I use to store index of a particular word. What I need to know is how do I stop my thread when the page is turned or the index of the page changes. I am calling this function inside the updatePage(final CurlPage page, final int width, final int height, final int index) method of Curl activity. I hope I was able to explain my problem. Thanks!
EDIT: I would like to specify my question more clearly. How do I check if the thread is already running before starting another thread and stop the execution of the previous thread?

removeCallbacks(..) only stops pending messages (Runnables).If runnable is started then u can not stop it in this way. See the following :
removecallbacks-not-stopping-runnable

Related

How to make 10 fast clicks [UIautomator]

Im trying to make fast 10 clicks on the button using this
public static void fastClicks(String text, int index) throws Exception {
Thread.sleep(1000);
UiObject settingsButton = new UiObject(new UiSelector().resourceId(text).index(index));
Configurator cc = Configurator.getInstance();
cc.setActionAcknowledgmentTimeout(10);
for (int i = 1; i < 11; ++i){
settingsButton.click();
System.out.println("clicked "+ i + " ");
}
}
yes it makes 10 clicks but first click have a little delay or something like that so it doesn't work properly. All I need this is 10 ritmic clicks with same delay from 1 click to 10. How can I improve this code? Thank you :)
else I tried this code
public static void fastClicks(String text, int index, int clicksCount) throws Exception {
UiObject settingsButton = new UiObject(new UiSelector().resourceId(text).index(index));
for(int currentClickIndex = 0; currentClickIndex < clicksCount; currentClickIndex++) {
if(settingsButton.exists()) {
settingsButton.click();
Thread.sleep(40);
System.out.println("clicked " + currentClickIndex + " times");
}
}
}
still nothing.
Sorry, I don't have enough reputation to comment so I'll try to make this a proper answer.
Because this behavior is only seen by the first click, it might occurs because some configurations were made before (or after) the action itself. For instance:
https://android.googlesource.com/platform/frameworks/testing/+/master/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
public boolean click() throws UiObjectNotFoundException {
[...]
AccessibilityNodeInfo node = findAccessibilityNodeInfo(mConfig.getWaitForSelectorTimeout());
[...]
}
protected AccessibilityNodeInfo findAccessibilityNodeInfo(long timeout) {
[...]
while (currentMills <= timeout) {
node = getQueryController().findAccessibilityNodeInfo(getSelector());
if (node != null) {
break;
} else {
// does nothing if we're reentering another runWatchers()
UiDevice.getInstance().runWatchers();
}
[...]
}
return node;
}
To avoid this, you can try getting the object's bounds first and then calling getUiDevice().click(...) directly:
UiObject settingsButton = new UiObject(new UiSelector().resourceId(text).index(index));
Rect bounds = settingsButton.getBounds();
for (int i = 1; i < 11; ++i){
getUiDevice().click(bounds.centerX(), bounds.centerY());
System.out.println("clicked "+ i + " ");
}
(as suggested by #Rami Kuret https://stackoverflow.com/a/17497559/2723645)

Appending letters onto a TextField after 100 milliseconds

I'm trying to append letters from a specific string onto a TextField. This is what I've tried so far. But no luck.
What happens here is it just waits for 100 milliseconds and then displays the string directly.
outConsole = (TextView) findViewById(R.id.outconsole);
int i, j;
String fin = "";
final String in = "HELLO!";
i = in.length;
try{
for(j = 0; j < i; j++){
Thread.sleep(100);
fin = fin + in.charAt(j);
outConsole.setText(fin);
}
}catch(Exception e){}
}
How do I achieve this?
I would like something like this but slower:
https://www.youtube.com/watch?v=Ff-eDOGLuYw
Try using Handlers. Something like this should work:
Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
//update your ui
handler.postDelayed(this, 100);//this restarts the handler better to have some terminating condition
}
};
handler.postDelayed(runnable, 100);//starts the handler first time

Trying to create an efficient infinite looping frame animation routine for Android

Since AnimationDrawable's memory blows up after a few images, I needed to write my own. Google has some demonstrations regarding efficient frame animations, but it is very complicated(needlessly?).
Here is my initial approach, can I get some experts/smart ppl to chime in?
Create a Handler on the UI Thread.
create runables (A) for the handler.
inside the runables (A), I create AsyncTasks for each frame.
each AsyncTask is run using PostDelay to achieve desired frame rate.
the target ImageVew is set wigh the new frame from the AsyncTask.
Here is the code:
private void addTask(Handler handler, final String animationName, final int frameNumber, final AsyncTaskLoadBitmap asyncLoadBitmap, int frameIndex) {
Runnable runnable = new Runnable() {
#Override
public void run() {
int frameIdentifier = getResources().getIdentifier(animationName, "drawable", getPackageName());
Log.v("Runable","adding name");
new AsyncTaskLoadBitmap(imageView,thisActivity).execute(frameIdentifier);
}
};
boolean done = handler.postDelayed(runnable,100 + (100 * frameIndex));
Log.v("PostDelayed","Done");
}
The problem I'm having is making it loop and a way to stopping the loop.
What could be a better approach?
try this:
final ImageView iv = new ImageView(this);
setContentView(iv);
final int LOAD = 1;
final int SHOW = 2;
HandlerThread loader = new HandlerThread("frameLoader");
loader.start();
Callback callback = new Callback() {
int idx = 0;
int[] ids = {
R.drawable.ic_launcher, R.drawable.layer0, R.drawable.layer1,
};
Resources res = getResources();
#Override
public boolean handleMessage(Message msg) {
if (msg.what == LOAD) {
Log.d(TAG, "handleMessage LOAD " + Thread.currentThread().getName());
idx++;
if (idx < 18) {
Bitmap btm = BitmapFactory.decodeResource(res, ids[idx % ids.length]);
msg = mUIHandler.obtainMessage(SHOW, btm);
mUIHandler.sendMessage(msg);
}
} else
if (msg.what == SHOW) {
Log.d(TAG, "handleMessage SHOW " + Thread.currentThread().getName());
iv.setImageBitmap((Bitmap) msg.obj);
mBackgroundHandler.sendEmptyMessageDelayed(LOAD, 500);
}
return true;
}
};
mBackgroundHandler = new Handler(loader.getLooper(), callback);
mUIHandler = new Handler(callback);
mBackgroundHandler.sendEmptyMessage(LOAD);

java.lang.IndexOutOfBoundsException... But why?

After 3 hours of try i decided to ask here and see if someone can provide me a solution for this error: java.lang.IndexOutOfBoundsException: Invalid index 4, size is 4
Here is my code.
private ProgressBar progressBar;
private int progressStatus = 0;
private Handler handler = new Handler();
--------------------
status.setText(getString(R.string.init));
progressBar.setVisibility(View.VISIBLE);
final Map<String,?> keys = prefs.getAll(); //4 prefs atm inside.
final ArrayList<String> props = new ArrayList<String>();
final ArrayList<String> values = new ArrayList<String>();
if (keys != null) {
for(final Map.Entry<String,?> entry : keys.entrySet()) {
props.add(entry.getKey());
values.add(entry.getValue().toString());
}
final int total = props.size();
progressBar.setMax(total);
new Thread(new Runnable() {
public void run() {
while (progressStatus < total) {
progressStatus += 1;
handler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressStatus);
if (props.get(progressStatus) != null) {
writeProps(props.get(progressStatus), values.get(progressStatus));
status.setText(getString(R.string.writing) + ": " + props.get(progressStatus));
}
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (progressStatus == total) {
handler.post(new Runnable() {
public void run() {
progressBar.setVisibility(View.GONE);
progressStatus = total + 1;
myVoidOnFinish();
}
});
}
}
}).start();
}
I get the stuck here:
writeProps(props.get(progressStatus), values.get(progressStatus));
status.setText(getString(R.string.writing) + ": " + props.get(progressStatus));
The main problem is here
while (progressStatus < total) {
progressStatus += 1;
}
check value of your progress status it should be not greater than 3 while in you code it is 4 in last while index is only from 0 to 3. please set value of your progress status accordingly.
try this
while (progressStatus < total-1) {
progressStatus += 1;
}
The problem is you are setting the progressstatus value like following
final int total = props.size();
progressBar.setMax(total);
and you in the following line you are trying to get values of props ase
writeProps(props.get(progressStatus), values.get(progressStatus));
see that for the total size of 4 your progressStatus will be 4. But the maximum index of props and values will be 3. So here is the problem
you can set the value to 1 less than the size like
final int total = props.size() - 1;
You are using one extra index as you can use maximum up to 3. So please start it form zero and use less then check instead of less then equal to.

Trying to set textview

Here is my class it goes in to infinite loop please check where I am going wrong ... I am trying to get id's of image view making it random and then trying to set text view with imageview's description
public class Object {
int ObectIds[];
LinearLayout HUDDisplay;
int HudDisplayText[] = {R.id.HUD_Text_Element1,
R.id.HUD_Text_Element2,
R.id.HUD_Text_Element3,
R.id.HUD_Text_Element4,
R.id.HUD_Text_Element5,
R.id.HUD_Text_Element6,
R.id.HUD_Text_Element7};
TextView[] text;
View v;
Object(Context context,View vs) {
super();
ObectIds = new int[8];
HUDDisplay=(LinearLayout)vs.findViewById(R.id.HUD_Display);
for (int i = 0; i < 8; i++) {
ObectIds[i] = (R.id.imageView1) + i;
Log.d("ImageView", "Image Id's " + ObectIds[i]);
}
randomize(vs);
setTextView();
}
public void setTextView()
{
for(int i=0;i<8;++i)
{
text[i] =(TextView) HUDDisplay.findViewById(HudDisplayText[i]);
text[i].setText(v.getContentDescription());
}
}
public void randomize(View vs) {
for (int i = 0; i < 8; i++) {
while (true) {
shuffleArray(ObectIds);
v = vs.findViewById(ObectIds[i]);
Log.d("Image", "Image Id's " + v.getId());
if (!v.isClickable()) {
v.setClickable(true);
break;
}
}
}
}
static void shuffleArray(int[] ar) {
Random rnd = new Random();
for (int i = ar.length - 1; i >= 0; i--) {
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
}
Hey man I observed your code & found error in code :
Please compare following code with your code... Constructor
for (int i = 0; i < 8; i++) {
ObectIds[i] = **HudDisplayText[i]**;
Log.d("ImageView", "Image Id's " + ObectIds[i]);
}
You have a while(true) loop that you break from only if v is not clickable. What happens if v is clickable? Nothing in your code ever sets v to not clickable, and views by default are not clickable.
I notice you're using the Object class. Object is basically the root of which all classes extend. If you call super() in the constructor, it will call the super class constructor, which is Object as well... That might be the problem.
Try looking for tutorials on how to start with Java/Android, since you are also using variables names that are not recommended. E.g. in Java,:
- a Class starts with a Capital
- a variable, starts with lowercase
- a function starts with lowercase:
public class Captial
{
private int anIntegerStartsWithLowerCase;
private void functionsAreLowerCaseAsWell()
{
}
}
Also take a look at your loop... It looks like it is never ending

Categories

Resources