I'm trying to make a button compare its value to some other variable. In the onClick method i get an error saying Variable is accessed within inner class, needs to be declared final. The problem is that the variable is supposed to be changed, so i cannot make it final. How can i fix this? Here is my code:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class GameActivity extends Activity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
int partA = 9;
int partB = 9;
int correctAnswer = partA * partB;
int wrongAnswer1 = correctAnswer++;
int wrongAnswer2 = correctAnswer--;
TextView textObjectA = (TextView)findViewById(R.id.textPartA);
TextView textObjectB = (TextView)findViewById(R.id.textPartB);
Button buttonObjectChoice1 = (Button)findViewById(R.id.buttonChoice1);
Button buttonObjectChoice2 = (Button)findViewById(R.id.buttonChoice2);
Button buttonObjectChoice3 = (Button)findViewById(R.id.buttonChoice3);
buttonObjectChoice1.setText("" + correctAnswer);
buttonObjectChoice2.setText("" + wrongAnswer1);
buttonObjectChoice3.setText("" + wrongAnswer2);
buttonObjectChoice1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int answerGiven = Integer.parseInt("" + buttonObjectChoice1.getText());
if(correctAnswer==answerGiven) {
}
}
});
buttonObjectChoice1.setOnClickListener(this);
buttonObjectChoice1.setOnClickListener(this);
}
public void onClick(View view) {}
}
Two approaches:
Make buttonObjectChoice1 final:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
final Button buttonObjectChoice1 =(Button)findViewById(R.id.buttonChoice1);
...
buttonObjectChoice1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int answerGiven = Integer.parseInt("" + buttonObjectChoice1.getText());
...
}
});
}
Convert view at runtime:
buttonObjectChoice1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Button btn = (Button)v;
int answerGiven = Integer.parseInt("" + btn.getText());
...
}
});
Advantage of approach 2 is, it will reduce workload of compiler to generate accessor methods to access buttonObjectChoice1 object.
Try to declare the variables as private field of your class and update it accordingly in the method.
Related
I am trying to implement a WebSocket client in Android Studio.
My code works fine but I'd like to clear the text boxes after the data has been set. When I tried to clear my EditText boxes after the 'SEND' button is clicked I found that they were being cleared before they were being used.
If I use the following code the contents of the text boxes gets sent,
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button) findViewById(R.id.send);
output = (TextView) findViewById(R.id.output);
client = new OkHttpClient();
add = (EditText) findViewById(R.id.add_str);
cmd = (EditText) findViewById(R.id.cmd_str);
key = (EditText) findViewById(R.id.key_str);
data = (EditText) findViewById(R.id.data_str);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
start();
}
});
}
But if I use the following...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button) findViewById(R.id.send);
output = (TextView) findViewById(R.id.output);
client = new OkHttpClient();
add = (EditText) findViewById(R.id.add_str);
cmd = (EditText) findViewById(R.id.cmd_str);
key = (EditText) findViewById(R.id.key_str);
data = (EditText) findViewById(R.id.data_str);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
start();
add.getText().clear();
cmd.getText().clear();
key.getText().clear();
data.getText().clear();
}
});
}
I just get an empty string sent. How do I stop this? I have tried setting a sent flag that is only set after the text has been sent...
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
start();
if (sent){
add.getText().clear();
cmd.getText().clear();
key.getText().clear();
data.getText().clear();
sent = false;
}
}
});
...but the text never gets cleared.
Edit #1: Full MainActivity listing
package qdivision.org.websocketexample;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
public class MainActivity extends AppCompatActivity {
private Button start;
private TextView output;
private OkHttpClient client;
public EditText add;
public EditText cmd;
public EditText key;
public EditText data;
public boolean sent = false;
private final class EchoWebSocketListener extends WebSocketListener {
private static final int NORMAL_CLOSURE_STATUS = 1000;
#Override
public void onOpen(WebSocket webSocket, Response response) {
String addStr = add.getText().toString();
String cmdStr = cmd.getText().toString();
String keyStr = key.getText().toString();
String dataStr = data.getText().toString();
String dataFrame = "<" + addStr + "," + cmdStr + "," + keyStr + "," + dataStr + ">";
webSocket.send(dataFrame);
webSocket.close(NORMAL_CLOSURE_STATUS, "Goodbye !");
sent = true;
}
#Override
public void onMessage(WebSocket webSocket, String text) {
output("Receiving : " + text);
}
#Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
output("Receiving bytes : " + bytes.hex());
}
#Override
public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(NORMAL_CLOSURE_STATUS, null);
//output("Closing : " + code + " / " + reason);
}
#Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
output("Error : " + t.getMessage());
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button) findViewById(R.id.send);
output = (TextView) findViewById(R.id.output);
client = new OkHttpClient();
add = (EditText) findViewById(R.id.add_str);
cmd = (EditText) findViewById(R.id.cmd_str);
key = (EditText) findViewById(R.id.key_str);
data = (EditText) findViewById(R.id.data_str);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
start();
/*add.getText().clear();
cmd.getText().clear();
key.getText().clear();
data.getText().clear();*/
}
});
}
private void start() {
Request request = new Request.Builder().url("ws://192.168.1.84:81/").build(); //"ws://echo.websocket.org"
EchoWebSocketListener listener = new EchoWebSocketListener();
WebSocket ws = client.newWebSocket(request, listener);
client.dispatcher().executorService().shutdown();
}
private void output(final String txt) {
runOnUiThread(new Runnable() {
#Override
public void run() {
output.setText(output.getText().toString() + "\n\n" + txt);
}
});
}
}
First of all, about the sent flag. If you are using another thread for settings its value, does not mean, this thread has to wait for it to read the value. In the if statement, if it is not true, it will skip the body. So, as soon as start() is called, assuming that start() is running on another thread, this thread will read the next statement and skip the loop.
Try using something like an OnCompleteListener() provided with the API that you are using.
The same logic goes with the editText.getText().clear(). If you are trying to read the text in start() after any HTTP call, the program will not wait for it and execute the remaining statements.
Hope that helps
Since onOpen happens asynchronously, the values that you're trying to pass are already cleared by that time. The simplest way would be to assign the values from your EditTexts to variables and then read them in onOpen. You could also add a constructor to your Websocket implementation that accepts String as a parameter.
Maybe you can try:
data.setText("");
editText.getText().clear();
will clear the text box.
So I want to pass the data between the activities,so I've make that there's 3 separate integers should be send to the second activity,but i don't know why,the emulator keeps adding all of them. Basically,I making an app, at case of my course - i need to create an app that keeping score,in my case,app would keep the score,number of fouls,and number of corners during the football match. To set the data,we are clicking in special button (press score to increment score etc.) when we want to go to the second activity and see the detailed statistics we should see like 3 goals,6 fouls,and like 2 corners for team "A" during the match,but when i clicking in buttons (suppose that is 1 time for goal,2 times for fouls,and 3 times for corner the app should be like 1 goal,2 fouls,3 corner's but it keep adding all of integers,and it's like 6 goals,6 fouls,6 corners. What can be wrong?
Count activity (here program storage the value of integers)
public class CountActivity extends AppCompatActivity {
public int team_a_score;
public int team_a_foul;
public int team_a_corner;
public int team_b_score;
public int team_b_foul;
public int team_b_corner;
private Button goToDetailedStats;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_count);
goToDetailedStats = (Button) findViewById(R.id.go_to_stats);
goToDetailedStats.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openDetailedScore();
}
});
}
private void openDetailedScore() {
Intent intent = new Intent(this,DeatiledScoreActivity.class);
intent.putExtra("",team_a_score);
intent.putExtra("",team_a_foul);
intent.putExtra("",team_a_corner);
startActivity(intent);
}
public void resetScore(View view) {
team_a_score = 0;
display_a_score(team_a_score);
team_b_score = 0;
display_b_score(team_b_score);
}
private void display_a_score (int a_score){
TextView team_a_score_tv = (TextView) findViewById(R.id.team_a_score_tv);
team_a_score_tv.setText(String.valueOf(a_score));
}
private void display_b_score (int b_score){
TextView team_b_score_tv = (TextView) findViewById(R.id.team_b_score_tv);
team_b_score_tv.setText(String.valueOf(b_score));
}
public void increment_a_score(View view) {
team_a_score = team_a_score+1;
display_a_score(team_a_score);
}
public void increment_a_foul(View view) {
team_a_foul = team_a_foul+1;
}
public void increment_a_corner(View view) {
team_a_corner = team_a_corner+1;
}
public void increment_b_score(View view) {
team_b_score = team_b_score+1;
display_b_score(team_b_score);
}
public void increment_b_foul(View view) {
team_b_foul = team_b_foul+1;
}
public void increment_b_corner(View view) {
team_b_corner = team_b_corner+1;
}
}
Detailed activity have to receive data that we send as intent from Counting activity.
public class DeatiledScoreActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_deatiled_score);
int team_a_score_detail_int = 0;
int team_a_foul_detail_int = 0;
int team_a_corner_detail_int = 0;
int team_b_score_detail_int = 0;
int team_b_foul_detail_int = 0;
int team_b_corner_detail_int = 0;
Intent goal_intent = getIntent();
int goal = goal_intent.getIntExtra("", team_a_score_detail_int);
display_a_goal(goal);
Intent foul_intent = getIntent();
int foul = foul_intent.getIntExtra("", team_a_foul_detail_int);
display_a_foul(foul);
Intent corner_intent = getIntent();
int corner = corner_intent.getIntExtra("", team_a_corner_detail_int);
display_a_corner(corner);
}
public void display_a_goal(int score) {
TextView a_score = (TextView) findViewById(R.id.team_a_goal_detail);
a_score.setText(String.valueOf(score));
}
public void display_a_foul(int foul){
TextView a_foul = (TextView) findViewById(R.id.team_a_foul_detail);
a_foul.setText(String.valueOf(foul));
They cannot have the same key:
intent.putExtra("",team_a_score);
intent.putExtra("",team_a_foul);
intent.putExtra("",team_a_corner);
So in order to make it work set:
intent.putExtra("some",team_a_score);
intent.putExtra("some2",team_a_foul);
intent.putExtra("some4",team_a_corner);
Intent putExtra method accepts two arguments key - value.
I'm a newbie android programmer that want to set text from another class
Here is the code:
MainActivity.java
EventHandler eventHandler = new EventHandler();
reader.Events.addEventsListener(eventHandler);
This one another Class but still inside the MainActivity
class EventHandler implements RfidEventsListener {
// Read Event Notification
public void eventReadNotify(RfidReadEvents e){
TagData[] myTags = myReader.Actions.getReadTags(100);
if (myTags != null)
{
for (int index = 0; index < myTags.length; index++)
{
System.out.println("Tag ID " + myTags[index].getTagID());
//I want to settext here
}
}
}
// Status Event Notification
public void eventStatusNotify(RfidStatusEvents e) {
System.out.println("Status Notification: " +
e.StatusEventData.getStatusEventType());
}
}
Thanks.. Regards
You can only manipulate UI elements, when your code is executed on the UI thread.
class EventHandler implements RfidEventsListener {
// Read Event Notification
public void eventReadNotify(RfidReadEvents e){
TagData[] myTags = myReader.Actions.getReadTags(100);
if (myTags != null)
{
for (int index = 0; index < myTags.length; index++)
{
System.out.println("Tag ID " + myTags[index].getTagID());
//I want to settext here
final String myText = myTags[index].getTagID();
runOnUiThread(new Runnable() {
#Override
public void run() {
myEditText.setText(myText);
}
});
}
}
}
// Status Event Notification
public void eventStatusNotify(RfidStatusEvents e) {
System.out.println("Status Notification: " +
e.StatusEventData.getStatusEventType());
}
}
This can be easily achieved by: (tested example)
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
/**
* This class was created by Anthony M Cannon on 16/05/2018.
*/
public class MainActivity extends AppCompatActivity {
private TextView textView;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
EventHandler handler = new EventHandler();
handler.test();
}
class EventHandler {
void test() {
textView.setText("Hello, from EventHandler.");
}
}
}
I am not sure if i need two classes or not, if I do I need to know how to pass data from one class to another and if not I need to know how to add an onClickListener to a class that already implements onSeekBarChangeListener.
Here's what I have so far:
package com.codeherenow.sicalculator;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.SeekBar;
public class SICalculatorActivity extends Activity implements SeekBar.OnSeekBarChangeListener{
private int years;
private TextView YT;
private SeekBar bar;
private EditText principal = (EditText) findViewById(R.id.PA_field);
private EditText interest = (EditText) findViewById(R.id.IR_field);
public EditText pvalue;
public EditText ivalue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sicalculator);
bar = (SeekBar)findViewById(R.id.seekBar);
bar.setOnSeekBarChangeListener(this);
pvalue = (EditText) principal.getText();
ivalue = (EditText) interest.getText();
}
#Override
public void onProgressChanged (SeekBar seekBar,int i, boolean b){
years = i;
YT = (TextView) findViewById(R.id.Years);
YT.setText(years + " Year(s)");
}
#Override
public void onStartTrackingTouch (SeekBar seekBar){
}
#Override
public void onStopTrackingTouch (SeekBar seekBar){
}
}
You can simply put a comma between all interfaces that you are implementing. In this case you'd need to have
public class SICalculatorActivity extends Activity
implements SeekBar.OnSeekBarChangeListener, View.OnClickListener{
You can continue using this method to implement any number of interfaces.
You can implement as many interfaces as you need:
public class SICalculatorActivity extends Activity implements SeekBar.OnSeekBarChangeListener, View.OnClickListener {
private int years;
private TextView YT;
private SeekBar bar;
private EditText principal;
private EditText interest;
public EditText pvalue;
public EditText ivalue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sicalculator);
//should init here to avoid NullPointerException
principal = (EditText) findViewById(R.id.PA_field);
interest = (EditText) findViewById(R.id.IR_field);
bar = (SeekBar)findViewById(R.id.seekBar);
bar.setOnSeekBarChangeListener(this);
// set click listener - someView.setOnClickListener(this);
pvalue = (EditText) principal.getText();
ivalue = (EditText) interest.getText();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
// case R.id.someViewId:
//handle click
// break;
}
}
#Override
public void onProgressChanged (SeekBar seekBar,int i, boolean b){
years = i;
YT = (TextView) findViewById(R.id.Years);
YT.setText(years + " Year(s)");
}
#Override
public void onStartTrackingTouch (SeekBar seekBar){
}
#Override
public void onStopTrackingTouch (SeekBar seekBar){
}
}
I keep getting repeated issues with: variable is accessed from within inner class
every time i want to use an object etc from an onclicklistener etc.
I know the problem is that its not set to final, but if i set to final im not able to do anything to it before pressing the onclicklistener button...
Example i have an EditText field, which is filled with getText from an object, then i want to press an apply button and the object with the new text from the textfield.
This doesnt work when the object need to be final for the "inner class" to use it.
How do i best handle this? i keep running into this bloody phenonemon...
public class EditPicture extends Activity{
private EditText text;
private Button applyBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID itemID = (UUID)getIntent().getSerializableExtra("itemUUID");
PictureItem pi = new PictureItem("","");
final ArrayList<PictureItem> tempArray = PictureTalkFragment.array;
for(int i = 0; i < tempArray.size(); i++){
if(itemID.equals(tempArray.get(i).getId())){
pi = tempArray.get(i);
tempArray.remove(i);
}
}
setContentView(R.layout.picturetalk_edit_pic);
text = (EditText)findViewById(R.id.editName);
text.setText(pi.getTitle());
applyBtn = (Button)findViewById(R.id.applyChangeBtn);
applyBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tempArray.add(pi);
}
});
}
}
you should define tempArray variable outside of onCreate method.
public class EditPicture extends Activity{
private EditText text;
private Button applyBtn;
ArrayList<PictureItem> tempArray
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID itemID = (UUID)getIntent().getSerializableExtra("itemUUID");
PictureItem pi = new PictureItem("","");
tempArray = PictureTalkFragment.array;
for(int i = 0; i < tempArray.size(); i++){
if(itemID.equals(tempArray.get(i).getId())){
pi = tempArray.get(i);
tempArray.remove(i);
}
}
setContentView(R.layout.picturetalk_edit_pic);
text = (EditText)findViewById(R.id.editName);
text.setText(pi.getTitle());
applyBtn = (Button)findViewById(R.id.applyChangeBtn);
applyBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tempArray.add(pi);
}
});
}
}
The problem is that you add th picture to a temporary array which is not accesible when you click on it. I think that you can do something like this to define the array outside the inCreate function.
public class EditPicture extends Activity{
private EditText text;
private Button applyBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID itemID = (UUID)getIntent().getSerializableExtra("itemUUID");
PictureItem pi = new PictureItem("","");
final ArrayList<PictureItem> tempArray = PictureTalkFragment.array;
for(int i = 0; i < tempArray.size(); i++){
if(itemID.equals(tempArray.get(i).getId())){
pi = tempArray.get(i);
tempArray.remove(i);
}
}
setContentView(R.layout.picturetalk_edit_pic);
text = (EditText)findViewById(R.id.editName);
text.setText(pi.getTitle());
applyBtn = (Button)findViewById(R.id.applyChangeBtn);
applyBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(PictureTalkFragment.array != null){
PictureTalkFragment.array.add(pi);
}
}
});
}
}