So I've been at this for 2 days and still I can't get it working.
I've tried solutions of implementing runnable, asynctask but it just never seems to work with my code. Perhaps I implemented it the wrong way...
Anyway, I have the following code written. When I create this activity I want to show a progressdialog with the text "Loading". Problem is, you can't update GUI-elements from another thread. That is where I'm stuck.
Hope you can help me out!
PS: The reason i need a ProgressDialog is because the line
ArrayList<String> genres = MysqlHandler.getAllGenres();
Can take quite some time to load. Also i have some other activities which need to do the same, and there it can take up to 5 seconds to load.
public class GenreActivity extends Activity implements OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_genre);
try {
ArrayList<String> genres = MysqlHandler.getAllGenres();
LinearLayout layout = (LinearLayout) findViewById(R.id.AllGenreLayout);
for(int i = 0; i < genres.size(); i++)
{
Button myButton = new Button(this);
myButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.yellow_button));
myButton.setTextAppearance(this, R.style.ButtonText);
myButton.setText(genres.get(i));
myButton.setOnClickListener(this);
layout.addView(myButton);
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/// try :)
progressgialog.post(new Runnable(){
run ()
{
progressgialog.setMessage("asd");
}
})
//// catch :)
activity.runOnUiThread(new Runnable()
{
progressgialog.setMessage("asd");
});
I found a work-around and thought I would share it.
Since I was making another thread inside the oncreate method, I figured I could also make a thread when i was starting the intent. So instead of this code:
Intent inte = new Intent(FirstSearchActivity.this, GenreActivity.class);
startActivity(inte);
Now I'm doing:
//start the progress dialog
progressDialog = ProgressDialog.show(FirstSearchActivity.this, "", "Loading...");
new Thread()
{
public void run()
{
Intent inte = new Intent(FirstSearchActivity.this, GenreActivity.class);
startActivity(inte);
progressDialog.dismiss();
}
}.start();
Related
i am trying to display a Toast on the screen and when Toast fades off then move to the next question. I have tried with Thread but cannot seem to manage.
My code:
next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (getUserSelection()){
position = position + 3;
if (position < questionsArray.size()) {
curName = questionsArray.get(position).getName();
curArray = questionsArray.get(position).getAnswers();
curIscorrect = questionsArray.get(position).getIscorrect();
setupQuestionView(curName, curArray, curIscorrect);
} else {
StringGenerator.showToast(QuestionsActivity.this, "Your score : " + score + "/" + (questionsArray.size() / 3));
}
}else {
StringGenerator.showToast(QuestionsActivity.this, getString(R.string.noanswerselected));
}
}
});
and the getUserSelectionMethod:
private boolean getUserSelection() {
correct = (RadioButton)findViewById(group.getCheckedRadioButtonId());
if (correct == null){
return false;
}else {
correctAnswerText = correct.getText().toString();
if (map.get(correctAnswerText).equals(Constants.CORRECTANSWER)) {
score++;
setCorrectMessage();
return true;
} else {
setWrongMessage();
return true;
}
}
}
private void setCorrectMessage() {
correctToast = new Toast(QuestionsActivity.this);
correctToastView = getLayoutInflater().inflate(R.layout.correct, (ViewGroup) findViewById(R.id.correctRootLayout));
correctText = (TextView)correctToastView.findViewById(R.id.correctTextView);
correctText.setText(getString(R.string.correctAnswer));
correctToast.setDuration(Toast.LENGTH_SHORT);
correctToast.setView(correctToastView);
correctToast.show();
correctThread = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
correctToast.cancel();
}
});
correctThread.start();
}
private void setWrongMessage() {
wrongToast = new Toast(QuestionsActivity.this);
wrongToastView = getLayoutInflater().inflate(R.layout.wrong, (ViewGroup) findViewById(R.id.wrongRootLayout));
wrongText = (TextView)wrongToastView.findViewById(R.id.wrongTextView);
wrongText.setText(getString(R.string.wrongAnswer));
wrongToast.setDuration(Toast.LENGTH_SHORT);
wrongToast.setView(wrongToastView);
wrongToast.show();
wrongThread = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
wrongToast.cancel();
}
});
wrongThread.start();
}
Any suggestion on how to do this?
You can determine the toast visibility:
toast.getView().getWindowToken()
If the result is null, than your toast isn't visible anymore, and than you can run any code you want.
as stated in this answer you can start a thread that waits the duration of the Toast:
Thread thread = new Thread(){
#Override
public void run() {
try {
Thread.sleep(3500); // 3.5seconds!
// Do the stuff you want to be done after the Toast disappeared
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Toast.LENGTH_SHORT and Toast.LENGTH_LONG are only flags so you have to either hard code the duration or keep them in a constant. The durations are 3.5s (long) and 2s (short).
If you want to manipulate some of your views, you cannot do this in another thread than the "main" UI thread. So you have to implement a kind of callback/polling mechanism to get notified when the SleepThread has finished.
Check this answer to read about a couple of ways to do this. Probably the easiest of them to understand and implement is this:
After you started your Thread you can check if it is still alive and running by calling thread.isAlive(). In this way you can do a while loop that runs while the thread is running:
// start your thread
while(thread.isAlive()){}
// continue the work. The other thread has finished.
Please note that this is NOT the most elegant way to do this! Check the other possibilities in the answer I've mentioned above for more elegant solutions (especially the last one with the listeners is very interesting and worth reading!)
That's because the Thread class is purely executed in the background and you need to manipulate the view in the Main thread. To solve your issue just replace the Thread with AsynTask.
AsyncTask<Void,Void,Void> a = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
correctToast.cancel();
}
};
a.execute();
If you look at my code you can see my onPostExecute, this method is called in the Main Thread.
My Error was because i was trying to acess UI Elements through another Thread so modifying the code like this:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(500);
QuestionsActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
moveToNextQuestion();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
did the trick. I hope my answer helps someone!!!
I have a problem with my game - when the live is 0 it should show the game-over screen and finish the game-activity, but the screen freezes instead.
The code in the surface is:
if(live <= 0){
try {
gameThread.setGameRunning(false);
gameThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
gameOverHandler.post(new Runnable() {
#Override
public void run() {
gameOver.onGameOver(score);
}
});
}
And the Interface in the GameActivity:
#Override
public void onGameOver(int score) {
Intent gameOver = new Intent(this, GameOver.class);
gameOver.putExtra("score", score);
startActivity(gameOver);
gameEngine.stop();
this.finish();
}
The Game-thread loops the canvas drawing and the Engine the movements of the Characters.
I hope you can help me.
Thanks!
You must have initialised gameOverHandler somewhere in the code using
gameOverHandler = new Handler();
or
gameOverHandler = new GameOverHandler();
Try replacing it with
gameOverHandler = new Handler(Looper.getMainLooper());
or
gameOverHandler = new GameOverHandler(Looper.getMainLooper());
depending on what class you have actually used.
Sry my internet was down about the weekend i've solved it with the constructor
public GameSurface(Context context, OnGameOver onGameOver){
...
}
and in the MainActivity
gameSurface = new GameSurface(this, this);
and implementing OnGameOver
a litte bit rewrite for my code but its works...
I've been working on looping AsyncTask on Android. I used an idea suggested by one of user and I came up with this:
public void loopAsyncTaskGetter(){
final Handler handler = new Handler();
final Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
new GetTasksAsync().execute(getIntent().getStringExtra(MainActivity.EXTRA_ID));
} catch (Exception e) {
}
}
});
}
};
timer.schedule(doAsynchronousTask, 500, 1000*30);
}
My AsyncTask extending class looks like that:
class GetTasksAsync extends AsyncTask<String, Void, Void>{
ProgressDialog dialog;
#Override
protected void onPreExecute(){
//dialog stuff
super.onPreExecute();
}
#Override
protected Void doInBackground(String... data) {
//this method below returns JSON String from my PHP file
String jsonData = Webserv.getTaskJson(data[0]);
try {
JSONArray jsonArray = new JSONArray(jsonData);
for(int i=0; i<jsonArray.length(); i++){
//some json parsing, doesn't matter
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void v){
dialog.dismiss();
myAdapter.notifyDataSetChanged();
super.onPostExecute(v);
}
I call loopAsyncTaskGetter() on my onCreate() method of Activity and I expect to have things done once for 30 seconds, and again. The strange thing for me is, that sometimes it works once for 30 seconds, and sometimes it gets done f.e. 3 times in 5 seconds, like much more often. Could anybody tell me why it works this way? Where did I make a mistake?
Kind regards!
You don't cancel your Timer when you're done with it. And because of that, you probably have multiple timers running in the background. Pass your Timer as a parameter to your asynctask and cancel it in onPostExecute.
Progressbar will not show when I try to access it from a thread nor update the progress. I would prefer to just have a progress spinner be displayed until the network activity is complete, and this network activity is just to post some text data to the server.This is the code I have so far, any help is appreciated thanks,
Thread th = new Thread(){
public void run() {
try {
sleep(5000);
while(cnt < 5000){
activty.this.runOnUiThread(new Runnable(){
public void run()
{
ProgressBar pd = (ProgressBar)findViewById(R.id.progressBar1);
pd.setVisibility(0);
pd.setMax(100);
pd.setProgress(cnt);
cnt += 100;
}
});
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int cnt = 100;
};
th.start();
`
This is exactly the case where you would want to use AsyncTask, which processes data in a separate thread and contains methods publishProgress and onProgressUpdate to update your UI on the UI thread.
The Processes and Threads Guide has an example of how to implement an AsyncTask as well.
I want to show 1 to 100 in a changeable text. I like to use sleep()function so that it looks like that it is increasing form 1 to 100. my code is
for(int i= 0;i<100;i++) {
scorelevel.setText(String.valueOf(i));
try{
Thread.sleep(1000);
}catch (InterruptedException e) {
e.printStackTrace();
}
}
but it did not show properly. Any help or suggestion is appreciated.
Don't block UI thread, use AsyncTask instead
Use Timer and TimerTask to perform any time based task.
You can start counter using runOnUiThread to update textView as:
private boolean mClockRunning=false;
private int millisUntilFinished=0;
public void myThread(){
Thread th=new Thread(){
#Override
public void run(){
try
{
while(mClockRunning)
{
Thread.sleep(1000L);// set time here for refresh time in textview
YourCurrentActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
if(mClockRunning)
{
if(millisUntilFinished==100)
{
mClockRunning=false;
millisUntilFinished=0;
}
else
{
millisUntilFinished++;
scorelevel.setText(String.valueOf(millisUntilFinished));//update textview here
}
}
};
}
}catch (InterruptedException e) {
// TODO: handle exception
}
}
};
th.start();
}
You could use a TimerTask (link), too.