How can I make for loop wait in each iteration? - java

I am trying to wait after each for loop using Threads in my application but I have a problem. This for loop has to be executed when the film from URL is playing but...
Unfortunately the loop is executed with pauses that I put into the code and later the film starts with text updated. This should start simultaneously. The for loop and the film. During the film the texts should be updated one after another.
NOTE: I shorted the ArrayList dict to make code easier to understand.
NOTE2: The app tries to open video file from URL but it gives me a message:
W/MediaPlayer: Couldn't open (Video URL) : java.io.FileNotFoundException: No content provider: (Video URL).
EDIT: I am putting an entire class code for you.
public class Video extends Activity {
private VideoView videoView;
private TextView englishTrans1;
private TextView polishTrans1;
private TextView englishTrans2;
private TextView polishTrans2;
private TextView englishTrans3;
private TextView polishTrans3;
int j = 0;
int i =0;
public static final String TAG = "My tag";
ArrayList<Translations> dict = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
videoView = findViewById(R.id.video_view1);
MediaController mMedia = new MediaController(this);
mMedia.setMediaPlayer(videoView);
mMedia.setAnchorView(videoView);
videoView.setMediaController(mMedia);
String path1 = (HERE IS VIDEO URL);
Uri uri = Uri.parse(path1);
videoView.setVideoURI(uri);
videoView.start();
englishTrans1 = findViewById(R.id.english_trans1);
polishTrans1 = findViewById(R.id.polish_trans1);
englishTrans2 = findViewById(R.id.english_trans2);
polishTrans2 = findViewById(R.id.polish_trans2);
englishTrans3 = findViewById(R.id.english_trans3);
polishTrans3 = findViewById(R.id.polish_trans3);
dict.add(new Translations("kot","cat"));
dict.add(new Translations("pies","dog"));
dict.add(new Translations("kawa","coffee"));
dict.add(new Translations("herbata","tea"));
dict.add(new Translations("kościół","church"));
dict.add(new Translations("ślub","wedding"));
final Handler h = new Handler() {
#Override
public void handleMessage(#NonNull Message msg) {
for(Translations x : dict){
try {
synchronized (this) {
Thread.sleep(2000);
}
}catch (InterruptedException e){
}
switch (j) {
case 1: {
Log.d(TAG, "First word translated");
englishTrans1.setText(x.getEnglishWord());
polishTrans1.setText(x.getPolishWord());
break;
}
case 2: {
Log.d(TAG, "Second word translated");
englishTrans2.setText(x.getEnglishWord());
polishTrans2.setText(x.getPolishWord());
break;
}
case 3: {
Log.d(TAG, "Third word translated");
englishTrans3.setText(x.getEnglishWord());
polishTrans3.setText(x.getPolishWord());
break;
}
}
if (j < 3) {
j++;
} else {
j = 1;
}
}
}
};
Runnable r = new Runnable() {
#Override
public void run() {
h.sendEmptyMessage(0);
}
};
Thread t = new Thread(r);
t.start();
}
}
Translations.java class with constructor.
public class Translations {
private String polishWord;
private String englishWord;
public Translations(){
}
public Translations(String mPolishWord,String mEnglishWord){
polishWord = mPolishWord;
englishWord = mEnglishWord;
}
public String getPolishWord() {
return polishWord;
}
public void setPolishWord(String polishWord) {
this.polishWord = polishWord;
}
public String getEnglishWord() {
return englishWord;
}
public void setEnglishWord(String englishWord) {
this.englishWord = englishWord;
}
}

Why loop at all, The "subtitles" as that is what the code snippet is doing, are linked to the video.
What if the person scrubs the film and fast forwards or rewinds, Most subtitle setups have the sentence on screen linked with a timecode for the film, so you then have the subtitle triggered on a change of timecode on the playing video, and pass in the timecode so it will get the sentence for that part of the video and display it on screen.

I have found a solution. The issue was that I was trying to sleep the Thread in Handler. The JVM thought that the main thread should be paused, not the "t" Thread. I moved the Thread.sleep() method to run() and the for loop too. I left only switch() in the Handler to change the UI. It works right now.
final Handler h = new Handler() {
#Override
public void handleMessage(#NonNull Message msg) {
Translations x = dict.get(i-1);
switch (j) {
case 1: {
Log.d(TAG, "First word translated");
englishTrans1.setText(x.getEnglishWord());
polishTrans1.setText(x.getPolishWord());
break;
}
case 2: {
Log.d(TAG, "Second word translated");
englishTrans2.setText(x.getEnglishWord());
polishTrans2.setText(x.getPolishWord());
break;
}
case 3: {
Log.d(TAG, "Third word translated");
englishTrans3.setText(x.getEnglishWord());
polishTrans3.setText(x.getPolishWord());
break;
}
}
}
};
Runnable r = new Runnable() {
#Override
public void run() {
for(i = 0;i<dict.size();i++) {
try {
Thread.sleep(2000);
}catch (InterruptedException e){
}
if (j < 3) {
j++;
} else {
j = 1;
}
h.sendEmptyMessage(0);
}
}
};
Thread t = new Thread(r);
t.start();
}
}

Related

OutOfMemory Exception in Android-Java. Allocation failed due to fragmentation

So I developed an Android application which acts as a server for my Android game(two separated apps), both applications were written in Java.
Previously I got messages on the Log like: "Skipped 2000 frames. The main thread could be overworking".
This is the code of my app, it's made of only the MainActivity:
I tried to introduce concurrent Threads in order to make the main thread lighter. Now the skipped n frames message isn't showed anymore but messages such like the followings are shown anyways.
"Alloc concurrent copying GC freed", "Starting a blocking GC alloc", "Waiting for a blocking GC alloc", "WaitForGcToComplete blocked alloc on HeapTrim" and all of this ends with
Throwing OutOfMemoryError "Failed to allocate a 32 byte allocation with 15604408 free bytes and 14MB until OOM, target footprint 268435456, growth limit 268435456; failed due to fragmentation (largest possible contiguous allocation 0 bytes)" (VmSize 5539048 kB).
I tried to deallocate some objects (lines of code which contains "x = null") but it didn't solve. Furthermore I checked with a log if there is some sort of endless loop but it doesn't seem to be the case.
public class MainActivity extends AppCompatActivity {
private static ActivityMainBinding binding;
private WSocServer server;
private int port = 8080;
private boolean isOnline = false;
private static ArrayList<String> logs = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
binding.openConnection.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(!isOnline) {
isOnline = true;
server = new WSocServer(port);
server.start();
Toast toast = Toast.makeText(view.getContext(),"Server is on", Toast.LENGTH_LONG);
toast.show();
Log.i("WebSocket Server", "Started on port " + server.getPort());
}
else{
Snackbar snack = Snackbar.make(view ,"We are already online!", Snackbar.LENGTH_INDEFINITE);
snack.setAction("Got it", new View.OnClickListener() {
#Override
public void onClick(View view) {
snack.dismiss();
}
});
snack.show();
}
}
});
binding.closeConnection.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(isOnline) {
isOnline = false;
logs.clear();
Toast toast = Toast.makeText(view.getContext(),"Server is off", Toast.LENGTH_LONG);
toast.show();
try {
server.stop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else{
Snackbar snack = Snackbar.make(view ,"We are already offline!", Snackbar.LENGTH_INDEFINITE);
snack.setAction("Got it", new View.OnClickListener() {
#Override
public void onClick(View view) {
snack.dismiss();
}
});
snack.show();
}
}
});
}
private static void addOnView(){
ConstraintLayout cl = binding.logsView;
Handler h = new Handler(Looper.getMainLooper());
for(int i = 0; i < logs.size(); i++){
TextView tv = new TextView(binding.getRoot().getContext());
tv.setTextSize(16);
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
tv.setPadding(40,180*(i+1),40,0);
tv.setText(logs.get(i));
Runnable r = new Runnable() {
#Override
public void run() {
cl.addView(tv);
}
};
h.post(r);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
try {
server.stop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static class WSocServer extends WebSocketServer {
private List<String> matchUsers;
private Integer timerSeconds;
private UUID matchId;
//a key represents a match to which an array of extracted numbers is associated
private Hashtable<String,Integer[]> matchExtractedNumbers = new Hashtable<>();
private Hashtable<String, Collection<WebSocket>> matchClients = new Hashtable<>();
private Hashtable<String,Hashtable<String,ArrayList<String>>> users_scorePerMatch = new Hashtable<>();
private Hashtable<String,WebSocket> clientConnection = new Hashtable<>();
private void initTimer(){
timerSeconds = 60;
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
if(timerSeconds > 0) timerSeconds--;
else {
timerSeconds = 60; timer.cancel(); timer.purge();
}
}
};
timer.schedule(task,0L,1000L);
}
private String UsersListToString(List list){
return list.toString().replace("[","").replace("]","");
}
private Integer[] generateExtractedNumbers(){
Integer[] callerBoard = new Integer[90];
List<Integer> boardPool = new ArrayList<>();
boardPool.addAll(Arrays.asList(IntStream.rangeClosed(1,90).boxed().toArray(Integer[]::new)));
for(int i = 0; i < 90; i++){
int rng = ThreadLocalRandom.current().nextInt(0,90-i);
callerBoard[i] = boardPool.remove(rng);
}
return callerBoard;
}
private void initMatch(){
matchId = UUID.randomUUID();
Integer[] matchBoard = generateExtractedNumbers();
matchExtractedNumbers.put(matchId.toString(),matchBoard);
matchClients.put(matchId.toString(),clientConnection.values());
Hashtable<String,ArrayList<String>> matchData = new Hashtable<>();
for(String user: matchUsers) matchData.put(user,new ArrayList<>());
users_scorePerMatch.put(matchId.toString(), matchData);
}
private Integer getExtractedNumber(String match, Integer turn){
if(turn >= 90) return -1;
Integer[] thisMatchExtractedNumbers = matchExtractedNumbers.get(match);
Integer returning = thisMatchExtractedNumbers[turn];
thisMatchExtractedNumbers = null;
return returning;
}
public WSocServer(int port){
super(new InetSocketAddress(port));
}
public WSocServer(InetSocketAddress address) {
super(address);
}
#Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket(open)", conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!");
logs.add(conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!");
matchUsers = new ArrayList<>();
matchUsers.addAll(Arrays.asList("user1","user2","user3","user4","user5"));
}
});
thread.start();
}
#Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket(close)", conn + " has left the room! Reason: " + reason);
logs.add(conn + " has left the room!");
}
});
thread.start();
}
#Override
public void onMessage(WebSocket conn, String message) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
logs.add(message + " from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
Log.i("WebSocket(message)", conn + ": " + message);
MainActivity.addOnView();
if(message.startsWith("username")){
if(matchUsers.size() < 6){
String user = message.replace("username;","");
if(!matchUsers.contains(user)) {
matchUsers.add(user);
clientConnection.put(user,conn);
}
String sending = "matchUsers;" + UsersListToString(matchUsers);
conn.send(sending);
}
else conn.send("errorUsername");
}
else if(message.equals("timerStart")){
initTimer();
if(matchUsers.size() < 6){
String sending = "timeStarter;" + timerSeconds.toString();
conn.send(sending);
}
else conn.send("errorTimer");
}
else if(message.equals("getMatchId")){
if(!matchUsers.isEmpty()){
initMatch();
matchUsers.clear();
}
String sending = "matchId;" + matchId.toString();
conn.send(sending);
}
else if(message.startsWith("inGame")){
String[] fields = message.split(";");
String matchId = fields[1].split("=")[1];
int turn = Integer.parseInt(fields[2].split("=")[1]);
Integer extraction = getExtractedNumber(matchId,turn);
fields = null;
conn.send("extracted=" + extraction.toString());
}
else if(message.startsWith("score")){
String matchId = message.split(";")[1].split("=")[1];
String score = message.split(";")[0].split("=")[1];
WebSocket[] clients = matchClients.get(matchId).toArray(new WebSocket[0]);
String user = "";
Enumeration<String> keys = clientConnection.keys();
String key = keys.nextElement();
while(!key.isEmpty()){
if(clientConnection.get(key) == conn) {
user = key;
break;
}
key = keys.nextElement();
}
keys = null;
Hashtable<String,ArrayList<String>> tmp = users_scorePerMatch.get(matchId);
ArrayList<String> tmp_list = tmp.get(user);
tmp_list.add(score);
tmp.replace(user,tmp_list);
users_scorePerMatch.replace(matchId,tmp);
for(int i = 0; i < clients.length; i++){
clients[i].send("statement;" + user + " got " + score + " with");
}
clients = null;
}
else if(message.startsWith("endMatchData")){
String matchId = message.split(";")[1].split("=")[1];
Hashtable<String,ArrayList<String>> users_ofMatch = users_scorePerMatch.get(matchId);
ArrayList<String> users = new ArrayList<>();
Enumeration<String> e = users_ofMatch.keys();
while(e.hasMoreElements()){
Log.e("endmatchdata","a");
users.add(e.nextElement());
}
e = null;
String sending = "matchEndData;";
for(String user: users) sending += user + "=" + UsersListToString(users_ofMatch.get(user)) + ":";
users_ofMatch = null;
conn.send(sending);
}
else if(message.startsWith("totalEnd")){
String matchId = message.split(";")[1].split("=")[1];
if(matchClients.get(matchId)!=null) {
WebSocket[] clients = matchClients.get(matchId).toArray(new WebSocket[0]);
for (WebSocket client : clients) client.close();
Enumeration<String> e = clientConnection.keys();
boolean exit = false;
while (e.hasMoreElements() && !exit) {
Log.e("totalend", "while");
for (WebSocket client : clients) {
Log.e("totalend", "for");
String tmp = e.nextElement();
if (clientConnection.get(tmp) == client) {
clientConnection.remove(tmp);
exit = true;
break;
}
}
}
e = null; clients = null;
matchClients.remove(matchId);
users_scorePerMatch.remove(matchId);
matchExtractedNumbers.remove(matchId);
}
}
}
});
thread.start();
}
#Override
public void onMessage(WebSocket conn, ByteBuffer message) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket(message)", conn + ": " + message );
}
});
thread.start();
}
public static void main(String[] args){
}
#Override
public void onError(WebSocket conn, Exception ex) {
ex.printStackTrace();
}
#Override
public void onStart() {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
Log.i("WebSocket", "Server started!");
}
});
thread.start();
}
}
}
EDIT: The thing seems to be happening at the end of the match(i.e in the message.startsWith("totalEnd") or message.startsWith("endmatchdata") if cases in the onMessage method
EDIT 2: I found out that the addOnView function was badly written.
I changed it into
private static void addOnView(){
ConstraintLayout cl = binding.logsView;
Handler h = new Handler(Looper.getMainLooper());
final TextView tv = new TextView(binding.getRoot().getContext());
tv.setTextSize(16);
tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
tv.setPadding(40,180*(logs.size()+1),40,0);
tv.setText(logs.get(logs.size()-1));
Runnable r = new Runnable() {
#Override
public void run() {
cl.addView(tv);
}
};
h.post(r);
h = null;
r = null;
}
And it solved.

Handlers don't end after calling removeCallbacksAndMessages(null)

I have two handlers. Handler in a handler. Both of them are in a for-loop.
The overview is something like this,
for{
handler.postDelayed(runnableA{
for{
handler2.postDelayed(runnableB{
function();
}, 3000);
}
}, 1000);
}
I wanted to end handlers' work at any time when the user clicks back button. So, I created two Runnable Classes so that I can use something like runnableA.removellbacksAndMessages(null).
Handler messageHandler;
Handler countDownHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, "Start Play in 5 seconds", Toast.LENGTH_SHORT).show();
countDownHandler = new Handler();
for (int i = 7; i >= 0; --i) {
final int idx = i;
Runnable countRunnable = new CountRunnable(idx, countDownView);
countDownHandler.postDelayed(countRunnable, 1000 * (7 - i));
}
}
And this is Runnable Classes.
public class CountRunnable implements Runnable {
int idx;
TextView countDownView;
public CountRunnable(int idx, TextView countDownView) {
this.idx = idx;
this.countDownView = countDownView;
}
#Override
public void run() {
int messageSize = messageItems.size();
for (int j = 0; j < messageSize; j++) {
final int jdx = j;
messageHandler = new Handler();
Runnable messageRunnable = new MessageRunnable(jdx);
messageHandler.postDelayed(messageRunnable, 3000 * jdx);
}
}
}
class MessageRunnable implements Runnable {
int jdx;
public MessageRunnable(int jdx) {
this.jdx = jdx;
}
#Override
public void run() {
addMessageView(messageItems.get(jdx));
}
}
This is onBackPressed():
#Override
public void onBackPressed() {
super.onBackPressed();
Toast.makeText(getApplicationContext(), "All Work Ended.", Toast.LENGTH_SHORT).show();
scrollFlag = true;
try {
messageHandler.removeCallbacksAndMessages(null);
} catch (Exception e) {
Log.d(TAG, "messageHandler never used");
e.printStackTrace();
}
try {
countDownHandler.removeCallbacksAndMessages(null);
} catch (Exception e) {
e.printStackTrace();
}
}
public void addMessageView(String message){
try{
mTextView.setText(message);
}catch(Exception e){
Toast.makeText(getApplicationContext(), "Abnormal End", Toast.LENGTH_SHORT).show();
}
}
But, I keep getting errors because the activity already ended but the handlers can't find the activity. So, Abnormal End Toast message shows as many as the size of inner for loop.
I can ignore this if I don't use the Toast message, but I am afraid of Memory leak or Bad formed Program or something like that.
How can I fix this problem?
The main problem is that you are creating n numbers of CountRunnables and m number MessageRunnables. Despite creating more than one numbers of handlers you are removing callbacks only for the latest-created Hanlder.
Here's what you should do:
Keep a reference of all the Handlers and Runnables and call messageHandler.removeCallbacksAndMessages(null); and countDownHandler.removeCallbacksAndMessages(null); on all of them.

Display a String letter by letter in a TextView -Android

I have this code:
public void setText(String s){
TextView tv= (TextView)HomeActivity.tf.getView().findViewById(R.id.textViewFragment);
char c;
for(int i=0; i< s.length(); i++){
c= s.charAt(i);
tv.append(String.valueOf(c));
try{
Thread.sleep(100);
}catch(Exception e){}
}
}
The problem is that i cant get the TextView to display the letters one-by-one. After the loop is completed and everything is executed, thats when the text shows up.
I want to have it show up letter by letter, to give an animation effect to the TextView.
This code works,
public void setText(final String s)
{
TextView tv= (TextView)HomeActivity.tf.getView().findViewById(R.id.textViewFragment);
final int[] i = new int[1];
i[0] = 0;
final int length = s.length();
final Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
char c= s.charAt(i[0]);
Log.d("Strange",""+c);
tv.append(String.valueOf(c));
i[0]++;
}
};
final Timer timer = new Timer();
TimerTask taskEverySplitSecond = new TimerTask() {
#Override
public void run() {
handler.sendEmptyMessage(0);
if (i[0] == length - 1) {
timer.cancel();
}
}
};
timer.schedule(taskEverySplitSecond, 1, 500);
}
Just in case someone's still looking for a better solution (with animating letters), try out Fade-In TextView.
This TextView library inherits its properties directly from the native TextView class, which means that all the native TextView methods are supported. There are practically no limitations including multiline support. It also has some of its own methods and attributes which offer full control over the View.
More simple
Thread thread = new Thread() {
int i;
#Override
public void run() {
try {
for (i = 0; i < text.length(); i++) { // use your variable text.leght()
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(text.substring(0, i));
}
});
}
} catch (InterruptedException e) {
}
}
};
thread.start();

Two-Dimensional Array with JSON data - Data is downloaded, but I can't access it (?)

So, I am creating a little trivia game for learning purposes, but I ran into a problem.
First, I had a specific Android Fragment obtaining the data from JSON, and I will simply use that data on the callback method and display it on TextViews and Buttons. Everything was working fine, however, every time I returned to that fragment, the same questions would be there. So I decided to handle that in a better way outside of the callback method.
The problem here is that apparently my Arrays are either null or their lengths is zero. Which is weird, because according to my LOG, data is being passed to those arrays on the callback method.
Here's my full fragment code. Thanks!
public class GameFragment extends Fragment {
private TextView txtQuestion;
private Button btnAnswer1;
private Button btnAnswer2;
private Button btnAnswer3;
private Button btnAnswer4;
private Questions[] gameQuestions;
private Questions[] animeQuestions;
private Questions[] techQuestions;
private Questions[] movieQuestions;
private Questions[][] gameCategories = new Questions[4][];
int correctAnswer = -1;
private TransparentProgressDialog progressBar;
private Handler handler;
private Runnable runnable;
Callback cb = new Callback<MyApiData>(){
#Override
public void success(MyApiData myApiData, Response response) {
gameCategories[0] = new Questions[myApiData.getCategory()[0].getQuestions(0).length];
gameCategories[1] = new Questions[myApiData.getCategory()[1].getQuestions(1).length];
gameCategories[2] = new Questions[myApiData.getCategory()[2].getQuestions(2).length];
gameCategories[3] = new Questions[myApiData.getCategory()[3].getQuestions(3).length];
//gameCategories = new Questions[][] {gameQuestions, animeQuestions, techQuestions, movieQuestions};
for(int i = 0; i < 4 ; i++){
for(int j = 0; j < gameCategories[i].length ; j++){
gameCategories[i][j] = myApiData.getCategory()[i].getQuestions(i)[j];
//Log.d("GameFragment", "gameCategories[i][j] - gameCategories["+i+"]["+j+"]: " + gameCategories[i][j].getQuestion());
}
}
//displayQuestion();
progressBar.dismiss();
displayQuestion();
}
#Override
public void failure(RetrofitError error) {
Log.d("GameScreen", "Callback failed!");
}
};
public GameFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_game, container, false);
txtQuestion = (TextView) view.findViewById(R.id.txtQuestion);
btnAnswer1 = (Button) view.findViewById(R.id.btnAnswer1);
btnAnswer2 = (Button) view.findViewById(R.id.btnAnswer2);
btnAnswer3 = (Button) view.findViewById(R.id.btnAnswer3);
btnAnswer4 = (Button) view.findViewById(R.id.btnAnswer4);
btnAnswer1.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View view) { checkAnswer(view); } });
btnAnswer2.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View view) { checkAnswer(view); } });
btnAnswer3.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View view) { checkAnswer(view); } });
btnAnswer4.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
checkAnswer(view);
}
});
handler = new Handler();
progressBar = new TransparentProgressDialog(getActivity(), R.drawable.loading_spinner);
runnable = new Runnable() {
#Override
public void run() {
if (progressBar.isShowing()) {
progressBar.dismiss();
}
}
};
//launchRingDialog();
//RestClient.get().getQuestions(cb);
// Inflate the layout for this fragment
return view;
}
public void launchRingDialog() {
new Thread(new Runnable() {
public void run(){
try {
Log.d("Thred", "Try");
progressBar.show();
RestClient.get().getQuestions(cb);
//Thread.sleep(10000);
} catch (Exception e) {
}
//progressBar.dismiss();
}
}).start();
}
public void checkAnswer(View v){
switch(v.getId()){
case R.id.btnAnswer1:
if(correctAnswer == 1){
feedback(true, btnAnswer1);
}else {
feedback(false, btnAnswer1);
}
break;
case R.id.btnAnswer2:
if(correctAnswer == 2){
feedback(true, btnAnswer2);
}else {
feedback(false, btnAnswer2);
}
break;
case R.id.btnAnswer3:
if(correctAnswer == 3){
feedback(true, btnAnswer3);
}else {
feedback(false, btnAnswer3);
}
break;
case R.id.btnAnswer4:
if(correctAnswer == 4){
feedback(true, btnAnswer4);
}else {
feedback(false, btnAnswer4);
}
break;
default: txtQuestion.setText("Error");
break;
}
}
public void feedback(Boolean correct, Button btn){
if(correct){
btn.setBackgroundColor(Color.GREEN);
btn.setText("CORRECT!");
}else{
btn.setBackgroundColor(Color.RED);
btn.setText("WRONG!");
}
}
#Override
public void onResume() {
super.onResume();
//displayQuestion();
}
public void displayQuestion(){
Random randomizer = new Random();
int randomQuestion;
int category = GTMain.choosenCategory;
if(category == 5){
category = randomizer.nextInt(4);
}
randomQuestion = randomizer.nextInt(25);
Log.d("displayQuestion", "Before if statements");
if(gameCategories != null && gameCategories.length != 0) {
Log.d("displayQuestion", "First if");
if(gameCategories[category] != null && gameCategories[category].length != 0){
Log.d("displayQuestion", "Second if");
txtQuestion.setText(gameCategories[category][randomQuestion].getQuestion());
correctAnswer = gameCategories[category][randomQuestion].getCorrectAnswer();
Log.d("displayQuestion()", "correctAnswer: " + correctAnswer);
btnAnswer1.setText(gameCategories[category][randomQuestion].getAnswers().getA1());
btnAnswer2.setText(gameCategories[category][randomQuestion].getAnswers().getA2());
btnAnswer3.setText(gameCategories[category][randomQuestion].getAnswers().getA3());
btnAnswer4.setText(gameCategories[category][randomQuestion].getAnswers().getA4());
}
}
}
}
PS: On my main activity, I check to see which fragment should be loaded. If it's the fragment that contains the components to display the questions and answer (the one from the code above), I call the following method: gameFragment.launchRingDialog(); (and yes, I have created an instance of my GameFragment fragment before calling that method!)
When onResume() is called, your RestClient.get().getQuestions(cb) is still running in background, and your call displayQuestion(), so of course nothing is shown.
Can you put displayQuestion() inside success() of your callback?
Callback cb = new Callback<MyApiData>(){
#Override
public void success(MyApiData myApiData, Response response) {
....
for(int i = 0; i < 4 ; i++){
for(int j = 0; j < gameCategories[i].length ; j++){
...
}
}
displayQuestion();
}
....
};
I would also suggest you to remove displayQuestion() in onResume() method.

Stuck in a loop, freezing the android app

I found out that when i pressed a button to run a while loop, the android app will freeze although the program can run. It seem that i stuck in a loop and i want to make a thread to show the GUI and the other for the main code . I'm new in java and i'm self-learned so i would appreciated if anyone could give me an example how to prevent the app from freezing.
I'm sorry if i didn't explain my problem well.
Thank you
Here is my code
public class TachoCount extends Thread {
public boolean isConnected;
protected static final String TAG = "TachoCount";
NXTConnector conn;
//_message = (TextView) findViewById(R.id.messageText);
//final TextView textView = (TextView) findViewById(R.id.textView1);
public static NXTConnector connect(final CONN_TYPE connection_type) {
Log.d(TAG, " about to add LEJOS listener ");
NXTConnector conn = new NXTConnector();
conn.setDebug(true);
conn.addLogListener(new NXTCommLogListener() {
public void logEvent(String arg0) {
Log.e(TAG + " NXJ log:", arg0);
}
public void logEvent(Throwable arg0) {
Log.e(TAG + " NXJ log:", arg0.getMessage(), arg0);
}
});
switch (connection_type) {
case LEGO_LCP:
conn.connectTo("btspp://NXT", NXTComm.LCP);
break;
case LEJOS_PACKET:
conn.connectTo("btspp://");
break;
}
return conn;
}
public TachoCount() {
}
public void closeConnection() {
try {
Log.d(TAG, "TachoCount run loop finished and closing");
conn.getNXTComm().close();
} catch (Exception e) {
} finally {
conn = null;
}
}
public void establishConnection(){
conn = TachoCount.connect(CONN_TYPE.LEGO_LCP);
NXTCommand.getSingleton().setNXTComm(conn.getNXTComm());
NXTInfo info = conn.getNXTInfo();
if (info.connectionState== NXTConnectionState.LCP_CONNECTED)
{
isConnected = true;
// set
//textView.setText("NXT is here");
}
}
public void forward(){
Motor.A.setSpeed(300);
Motor.C.setSpeed(300);
Motor.A.forward();
Motor.C.forward();
}
public void backward(){
Motor.A.setSpeed(300);
Motor.C.setSpeed(300);
Motor.A.backward();
Motor.C.backward();
}
public void byebye(){
Motor.A.stop();
Motor.C.stop();
}
public int getSensorValue()
{
int val = 0;
LightSensor ls = new LightSensor(SensorPort.S3);
val = ls.readValue();
return val;
}
public void linefollower()
{
run();
}
public void run()
{
int min = 30, max = 37, readLight = 0, Mspeed = 90, Mspeed2 = 20;
LightSensor ls = new LightSensor(SensorPort.S3);
while(true){
Motor.A.forward();
Motor.C.forward();
readLight = ls.readValue();
LeJOSDroid.sendMessageToUIThread("Sensor: "+ls.readValue());
if (readLight < min){
readLight = min+1;
}
if (max < readLight){
readLight = max-1;
}
Motor.C.setSpeed(Mspeed + (Mspeed2 * (readLight - min)));
Motor.A.setSpeed(Mspeed + (Mspeed2 * (max - readLight)));
}
}
i tried to change the code. It runs well (although the reading of the
sensor doesn't seem accurate), but then when i push another button,
nothing happens
public void linefollower()
{
Thread thread = new Thread(runnable);
thread.start();
}
Runnable runnable = new Runnable ()
{
public void run(){
int min = 30, max = 37, readLight = 0, Mspeed = 90, Mspeed2 = 20;
LightSensor ls = new LightSensor(SensorPort.S3);
while(true){
Motor.A.forward();
Motor.C.forward();
readLight = ls.readValue();
LeJOSDroid.sendMessageToUIThread("Sensor: "+ls.readValue());
if (readLight < min){
readLight = min+1;
}
if (max < readLight){
readLight = max-1;
}
Motor.C.setSpeed(Mspeed + (Mspeed2 * (readLight - min)));
Motor.A.setSpeed(Mspeed + (Mspeed2 * (max - readLight)));
}
}
};
Try using Runnable or background worker
Your loop looks infinite, it's always true. Also, it's probably better to do heavy tasks in an asynctask activity.
Check the official info: http://developer.android.com/reference/android/os/AsyncTask.html

Categories

Resources