i need some good advice for my code.
here is what i want to do.
i have an activity that has some views that can be selected by user. assumed that the user selected a view, i want to deselect this view automatically after, let's say, 5 seconds.
I do this by a thread.
when the user selects the view, i call...
Deselector deselect = new Deselector(mp.getDuration(), clickedview);
deselect.start();
...in the activity.
the deselector class:
class Deselector extends Thread
{
int millis=0;
View view = null;
Deselector(int millis, View view)
{
this.millis = millis;
this.view = view ;
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
this.sleep(millis);
view.setSelected(false);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
my program crashes and logkitty says
12-11 14:29:37.457: ERROR/AndroidRuntime(3263): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
how to do it right?
thanks in advance
m.d.
Use postDelayed() on a widget or a Handler, rather than a background thread, to do work after your proposed delay.
i got it working by doing the following
clickedview.postDelayed(new Deselector(clickedview), mp.getDuration());
with my deselctor runnable now a bit shorter:
class Deselector implements Runnable
{
View view = null;
Deselector(View view)
{
this.view = view ;
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
view.setSelected(false);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Related
I am wondering about the post method use into the Thread class.
My program is about to find fixed salary from the basic salary.Basically in this program ,I have one editText where user have to enter the basic salary and when the click on the button called 'show' there is one counter which display on the screen 1,2,3,...10 in textview.Then after the fixed salary will displayed on other editText.So,this about my program
Now,In code I have make one class called Mythread for the counter purpose.In which I have put the loop which count 1,2,...10.But my problem is that the i want to refresh the values of the textView so i want to use post method but how to use in my code that i don't know.
Kindly guide me
package com.example.bs_to_fs_thread;
import android.widget.TextView;
public class MyThread extends Thread{
TextView _tv;
String fs;
public MyThread(TextView tv,String sfs){
_tv=tv;
fs=sfs;
}
public void run()
{
int i=0;
while(i<10)
{
_tv.post(new Runnable()
{
public void run()
{
_tv.setText(i);
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
MainActivity.printFS(fs);
}
}
`
In this code ,may be I write the _tv.post(Runnable{ });
on wrong place pls give me the view of this post method and how should and where should i write this post method? and why?
Try something like this(I have not tested it dont have editor now):
public MyThread(TextView tv,String sfs,Activity a){
this._tv=tv;
this.fs=sfs;
this.a= a;//this is required to use method runOnUiThread as background thread cannot modify Ui thread
}
Then in the place where you want to modify your UI like change text do something like this:
a.runOnUiThread(new Runnable() {
public void run()
{
Toast.makeText(a, "show some toast", Toast.LENGTH_SHORT).show();
_tv.setText("mytext");
}
});
Try this:
public void run() {
int i = 0;
while(i < 10) {
// We can't use 'i' directly inside the runnable declaration, because all
// external variables must be declared as final
final int number = i;
// Posting this runnable to the UI thread
_tv.post(new Runnable() {
public void run() {
_tv.setText(number);
}
}
// Sleeping current thread (NOT UI thread) for 1 second
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Increment 'i'
i++;
}
MainActivity.printFS(fs);
}
I have a fragment that has an animation of textView fadein. The animation must start after some time delay say 2 seconds after fragment is loaded. I wrote a code for this. but the animation part is done and then the view is rendered. How can I load the fragment and after some time delay start my animation
My code is as below: Note: the class extends Fragment
Animation animFadein;
MenuClickHelper mClickHelper;
TextView tv;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_main_menu,
container, false);
mClickHelper = new MenuClickHelper(rootView, getFragmentManager());
tv = (TextView) rootView.findViewById(R.id.tvPresentation);
animFadein = AnimationUtils.loadAnimation(getActivity()
.getApplicationContext(), R.anim.fade_in);
animFadein.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
if (animation == animFadein) {
Toast.makeText(getActivity().getApplicationContext(),
"Animation Stopped", Toast.LENGTH_SHORT).show();
}
}
});
try {
Thread.sleep(2000);
tv.startAnimation(animFadein);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rootView;
}
Thread.sleep(2000); dont block your main using the sleep method instead you can use the Handler class and use postdelay to delay the animation:
sample:
change this:
try {
Thread.sleep(2000);
tv.startAnimation(animFadein);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
to
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
tv.startAnimation(animFadein);
}
}, 2000); //will start animation in 2 seconds
You can achieve the same result with
android:startOffset="2000"
in your XML animation set file.
I am building a snake game, and it works, but with a little bug that really irritates me.
when I click on one of the buttons that in the xml, the snake changes it's direction according to the button.
the problem is that if you have clicked on a button after it's has already re-entered the loop inside the run() of the thread and entered the loop inside the the onDraw() (you can see in the code) it will first finish the loop of the run() and then re-enter and do the turn. and by that a delay is created from the click time to when it turns.
the turn works like this- there is a String variable that gets "LEFT","RIGHT", "UP" or "DOWN", according to what it gets it moves the snake. when you click on a button it changes the variable accoring to what button u have clicked on.
heres the code of how it moves the snake accoring to the direction:
public void onDraw(Canvas canvas){
switch(direction){
case "RIGHT"
xLoc=xLoc+PART_SIZE;
break;
case "UP"
yLoc=yLoc-PART_SIZE;
break;
case "LEFT"
xLoc=xLoc-PART_SIZE;
break;
case "DOWN"
yLoc=yLoc+PART_SIZE;
break;
}//swich
int x=xLoc;
int y=yLoc;
for(BodyPart bp:WholeBody){
Rect r=new Rect();
r.set(0+x, 0+y, PART_SIZE+x, PART_SIZE+y);
bp.setR(r);
canvas.drawRect(bp.getR(),bp.getP());
int xtemp=bp.getX();
int ytemp=bp.getY();
bp.setX(x);
bp.setY(y);
x=xtemp;
y=ytemp;
}//for each
}//onDraw
the xLoc and the yLoc is the location of where the head of the snake will go to, and the its moves each body part(each rect of the snake-each bodypart is an equall rect) the the location of where the bodypart before it was.
here are the onClick()s:
left.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="LEFT"&&gv.snake.getDir()!="RIGHT"){
gv.snake.Left();
}
}
});
right.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="RIGHT"&&gv.snake.getDir()!="LEFT"){
gv.snake.Right();
}
}
});
up.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="UP"&&gv.snake.getDir()!="DOWN"){
gv.snake.Up();
}
}
});
down.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="DOWN"&&gv.snake.getDir()!="UP"){
gv.snake.Down();
}
}
});
gv is an variable from class gameView which in it has a variable from the class snake
here are the setDirection:
public void Left(){
direction="LEFT";
}
public void Up(){
direction="UP";
}
public void Right(){
direction="RIGHT";
}
public void Down(){
direction="DOWN";
}
and here is the run of the thread:
public void run() {
long stepPerSecond=1000/FPS;
long startTime;
long sleepTime;
while(isRunning){
Canvas c= null;
startTime=System.currentTimeMillis();
try{
c=this.getHolder().lockCanvas();
synchronized (this.getHolder()) {
this.onDraw(c);
}
}
catch(Exception e){
}
finally{
if(c!=null){
this.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime= stepPerSecond-(System.currentTimeMillis()-startTime);
if(sleepTime>0)
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
else
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
is there someway that there will not be that delay?
maby when you click on a button it will stop the run() and redo it after it had updated the direction variable acording to the click.
I'm trying to do:
perform a TextToSpeech
SpeechRecognizer starts listening as the user repeats the
TextToSpeech'd word/phrases
But my problem is that, for example, if i were to say "example" via TextToSpeech, when the SpeechRecognizer starts listening, it also takes in the "example" from previous and adds onto the one that the user says. So at the end, i ended up "example example", which i didn't want.
Code:
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
item = (String) parent.getItemAtPosition(position);
tts.speak(item, TextToSpeech.QUEUE_FLUSH, null);
Thread thread = new Thread() {
public void run() {
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
sr.startListening(srIntent);
}
You are doing two process in Two thread. You are creating Thread One and make it sleep for 3 seconds and sr.startListening(srIntent); start Intent in separate UI Thread. So it start Intent Immediately. Use both process in one Thread like i post it below
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
item = (String) parent.getItemAtPosition(position);
tts.speak(item, TextToSpeech.QUEUE_FLUSH, null);
Thread thread = new Thread() {
public void run() {
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mSpeech.sendEmptyMessage(0);
}
};
thread.start();
}
Create one Inner Handler class to perform UI operations
private Handler mSpeech=new Handler(){
public void handleMessage(android.os.Message msg) {
sr.startListening(srIntent);
}
};
it must be within the run() body
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
item = (String) parent.getItemAtPosition(position);
tts.speak(item, TextToSpeech.QUEUE_FLUSH, null);
Thread thread = new Thread() {
public void run() {
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
sr.startListening(srIntent);
}
};
thread.start();
}
I have a ListView that has images in it and these images come from server, a loader downloads the images then in onLoadFinished it setAdapter of ListView. After setting adapter, I try to select first item of ListView, but it has no effect. I suspected that ListView is not ready to select yet so I managed to do that by a strange way like overriding setSelection function:
public void setSelection(final int position) {
// TODO Auto-generated method stub
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
Log.i(TAG, "thread runned.");
boolean is_view_created = false;
while (!is_view_created) {
try {
Thread.sleep(100);
getListView();
if (getListView().getChildAt(position) != null)
is_view_created = true;
else {
Log.i(TAG, "Waiting for the list view to initialize.");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
Log.i(TAG, "Waiting for the list view to initialize.");
}
}
MiddleMenuListFragment.super.setSelection(position);
View initial_selection_view = getListView().getChildAt(position);
initial_selection_view.performClick();
((MiddleMenuListAdapter)getListAdapter()).light_me_up = position;
getActivity().runOnUiThread(new Runnable(){
#Override
public void run() {
((MiddleMenuListAdapter)getListAdapter()).notifyDataSetChanged();
}
});
}
}, 400);
}
But this method is not really safe. It sometimes enters the loop (can't get getListView().getChildAt(position != null) true). Can you advise more elegant solution to the problem?
If you don't using header you can listen ListView hierarchy change with OnHierarchyChangeListener
private boolean needSelection = true;
public void onChildViewAdded(View parent, View child) {
if (needSelection && indexOfChild(child) == 0) {
trySelectChild(child);
needSelection = false;
}
}
Couldn't you just register a DataSetObserver against the ListAdapter to set the selection on the onChange() event once there is 1 or more items in the ListAdapter?