How to monitor a changing variable - android

This question has nothing to with debugging or in other words I'm not trying to monitor the value of a certain variable to verify if the code is running correctly. I have 6 buttons that can be enabled depending on a variable which we will call X. Each button has a different threshold of what X needs to be in order to enable that button. For example, button1 is enabled if X is at least 50, button2 if X is at least 165, etc. I can have an asynctask to poll variable X and enable or disable the buttons but is there a better way?

Add your variable to a class like so:
public class example {
private int X;
public int getX() { return X; }
public void setX(int x) {
X = x;
// When X is set notify your watchers
}
}
Next create an interface like so:
public interface VariableChangeWatcher {
public void variableChanged(int value);
}
If you make your class use this interface you can add watchers or listeners to know when the value of X has changed outside the class:
public class example {
VariableChangeWatcher watcher;
private int X;
public int getX() { return X; }
public void setX(int x) {
X = x;
// When X is set notify your watchers
if (watcher != null)
watcher.variableChanged(x);
}
}
Then in any class that uses example you can simply listen in to the interface to know when the value of X has changed:
public class exampleListener implements VariableChangeWatcher
{
public exampleListener() {
example e = new example();
}
#Override
public void variableChanged(int value) {
// Gets alerted when the X value inside our e variable has changed
}
}

Use encapsulation. Do not make x a variable. Make it a class, with a value inside it. Put a setter function on it. Then whenever the setter function is called, have it set the value and enable/disable all the proper buttons. This way you can't forget to do it anywhere- the only way to set it is via the setter method.

Related

Create boolean listener

In Android, how do I take an action whenever a variable changes?
So I want to implement a listener for an object I created. What I want it to do is execute a block of code when its value changes from false to true.
As I am following this thread, I can't understand where the person wants us to implement the last block of code containing the logic for the listener.
Could someone, hopefully, guide me in the right direction?
(This question is being asked here as I don't have enough rep. points)
That last bit of example code triggers the listener, so it basically needs to be run whenever the "event" occurs. In this case the "event" is whenever (wherever in the code) the value of the variable changes.
If you have a setter and that is the only place the value changes, that is where you'd put it. If you are changing the value in multiple places throughout your code, I would make a new private method (call it signalChanged), put your code there, and then call it immediately after the variable assignment in the cases you want the listener to fire.
Here's an example (some code borrowed from linked answer, haven't checked that it compiles).
public class MyObj
{
public MyObj(int value)
{
setValue(value);
}
private int myValue;
public int getValue() { return myValue; }
public void setValue( int value )
{
if (value != myValue)
{
myValue = value;
signalChanged();
}
}
public interface VariableChangeListener
{
public void onVariableChanged(Object... variableThatHasChanged);
}
private VariableChangeListener variableChangeListener;
public void setVariableChangeListener(VariableChangeListener variableChangeListener)
{
this.variableChangeListener = variableChangeListener;
}
private void signalChanged()
{
if (variableChangeListener != null)
variableChangeListener.onVariableChanged(myValue);
}
}
you have to create a callback interface
here is a good about custom listener tutorial
here is a sample
public class MyObj {
VariableChanger onVariableChanged ;
public void setOnVariableChanged(VariableChanger onVariableChanged) {
this.onVariableChanged = onVariableChanged;
}
void log(){
boolean changed = false;
onVariableChanged.onVariableChanged();
//this will call it
}
interface VariableChanger{
void onVariableChanged();
}
}
class logic {
MyObj mo = new MyObj();
void main(){
mo.setOnVariableChanged(new MyObj.VariableChanger() {
#Override
public void onVariableChanged() {
//do your action
}
});
}
}
In Android, like any language, most developper uses logic comparisons to check values (if, else, switch, =, !=, >, <, etc) or Event (signal)
What kind of listener do you want to implement?

Using a value from json file in Libgdx

I want to use a value from a json file
Here is the Json file
{
"button" : [
{
"x" : 50.0
},
{
"x" : 150.0
}
]
}
I have the following classes
(Button Class)
public class Button extends Sprite{
float x;
public Button() {
super(new Texture("button.png"));
}
#Override
public void setX(float x) {
this.x = x;
}
}
(Data Class)
public class Data {
public Array<Button> buttons;
public void load() {
buttons = new Array<Button>();
Json json = new Json();
json.setTypeName(null);
json.setUsePrototypes(false);
json.setIgnoreUnknownFields(true);
json.setOutputType(JsonWriter.OutputType.json);
json.fromJson(Data.class, Gdx.files.internal("buttons.json"));
}
}
(Main Class)
public class GameMain extends ApplicationAdapter {
SpriteBatch batch;
Data data;
#Override
public void create () {
batch = new SpriteBatch();
data = new Data();
data.load();
for(Button b : data.buttons) {
b.setX(b.x);
}
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
for(Button b : data.buttons) {
b.draw(batch);
}
batch.end();
}
}
I want to draw buttons in specific x positions that is held in json file
but it gives me nothing .
What is wrong in my code ?
Any ideas ?
at the end of load() you haven't asign the results. Just add buttons = :
public void load() {
//instead of this line:
//buttons = new Array<Button>();
Json json = new Json();
json.setTypeName(null);
json.setUsePrototypes(false);
json.setIgnoreUnknownFields(true);
json.setOutputType(JsonWriter.OutputType.json);
// set buttons here:
buttons = json.fromJson(Data.class, Gdx.files.internal("buttons.json"));
}
Your Data class loads another instance of a Data class and doesn't assign it to anything. It's circular and doesn't make sense. The load method should be static, return a Data object (which is what the last line of your current load method provides), and not be trying to instantiate an empty buttons array that goes unused.
Your button class hides both the x field and the setX method of the superclass, making it impossible to change the actual X position of the sprite that is used when it is drawn. Sprite already has an x parameter, so you should not be adding your own. If you merely remove those two things from your Button class, it should work.
That said, you should not be loading another copy of the same texture for each button. That's a waste of memory and texture swapping. And unless you are very careful about disposing the textures "owned" by these sprites, you are also leaking memory.

Pass value from Activity to custom View

I need to pass a value from my main Activity to a custom View.
In the main activity I have a SensorEventListener so I'm continuosly listening to the light sensor. In the onSensorChanged() method I read the value, and I need to send this value every time it changes to my custom View.
I don't know which is the best way to achive this.
UPDATE --
Method refered to SensorEventListener on main activity:
#Override
public void onSensorChanged(SensorEvent event) {
float lumnes = event.values[0];
GaugeView.setHandTarget(lumnes);
}
Method I have to send values to in custom view:
public void setHandTarget(float temperature) {
if (temperature < minDegrees) {
temperature = minDegrees;
} else if (temperature > maxDegrees) {
temperature = maxDegrees;
}
handTarget = temperature;
handInitialized = true;
invalidate();
}
I cannot use static references cause then I cannot call invalidate()
You could do this:
public CustomView extends View {
...
private float[] values; //this
//setter
public void setValues(float[] values) {
this.values = values;
}
}
public class MyActivity extends Activity implements SensorEventListener {
private CustomView mCustomView;
...
#Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
mCustomView.setValues(values); //pass the collected values to the view via setter
}
}
Without seeing any of your code, the best advice I can give is to create a property in your view, and make it accessible from your Main Activity class. In your method that is checking the sensor, you can simply set the custom View's property that you created to be the value. Not so much passing the value as directly accessing it.
Assuming your value is a float, add something like this to your Custom view class:
public float sensorValue;
Access it from the sensor event listener like this:
CustomView.sensorValue = sensorValue;

Android Get the next or previous Enum

I need a way to get the next/previous enum.
My problem is that I cannot iterate the normal way:
for( Mode m: Mode.values() ) {
. . .
}
I need to get the next enum inside a method, each time it is called:
Note that Mode is a system Enum, therefore I cannot define methods, unless I create my own Enum, which is a solution, but a less preferred one.
public class A {
private Mode m;
A() {
m = Mode.CLEAR;
}
...
protected onClick(View v) {
...
v.getBackground().SetColorFilter(R.color.azure, m);
m = m.next(); // <-- I need something like this
...
}
//Store these somewhere in your class
Mode[] modes = Mode.values();
int modeCount = modes.length;
protected void onClick(View v) {
//Get the next mode, wrapping around if you reach the end
int nextModeOrdinal = (m.ordinal() + 1) % modeCount;
m = modes[nextModeOrdinal];
}
For Kotlin, you can declare an extension function on all enum types that would allow you to define a next() function on all enum instances:
/**
* Returns the next enum value as declared in the class. If this is the last enum declared,
this will wrap around to return the first declared enum.
*
* #param values an optional array of enum values to be used; this can be used in order to
* cache access to the values() array of the enum type and reduce allocations if this is
* called frequently.
*/
inline fun <reified T : Enum<T>> Enum<T>.next(values: Array<T> = enumValues()) =
values[(ordinal + 1) % values.size]
Then you can have something like:
enum class MyEnum {
ONE, TWO, THREE
}
Then you can just use val two = MyEnum.ONE.next()
Implement this method:
public static Mode nextMode(Mode mode) {
return (mode.ordinal() < Mode.values().length - 1) ? Mode.values()[mode.ordinal() + 1] : null;
}

How to use callbacks in my own code

Here I update my world to include the canvas size
world.getViewPort().updateViewPortSize(width,height);
Is there a better way to do this? Is there a way that I can automatically update my world object without having to manually call it in the setSurfaceSize method but instead call it from My world class?
My guess is that I can use some sort of callback, but I don't understand them!
/* Callback invoked when the surface dimensions change. */
public void setSurfaceSize(int width, int height) {
// synchronized to make sure these all change atomically
synchronized (mSurfaceHolder) {
mCanvasWidth = width;
mCanvasHeight = height;
world.getViewPort().updateViewPortSize(width,height);
}
}
Callback functions are pretty straightforward in Java. The way to do it is to simply define some interface A that has a single method m(), then add a collection of type A to your World class. Then, at some point in your World object you want to iterate over your A collection and call the method m() on each element. To add "callback functions" to your World, you then simply define some class that implements your interface A and put it in the collection of A objects in your World class. For example,
public interface CallbackFunction
{
public void execute(int a, int b);
}
public class World
{
List<CallbackFunction> callbackFunctions;
public void addCallback(CallbackFunction f)
{
callbackFunctions.add(f);
}
private void updateWorld()
{
// This loop could be anywhere in your World class
for(CallbackFunction f : callbackFunctions)
{
f.execute(<some int>, <some int>);
}
}
}
Then to add a function to your World:
world.addCallback(new CallbackFunction()
{
public void execute(int a, int b)
{
// Do some stuff
}
}
I leave the rest up to you, but this should give you a good idea of how callbacks are typically implemented in Java.
You don't need to store a general collection of callback functions either, you could have specific callback functions coupled with particular methods in your World class. For instance, your World class may have some method that sorts things by comparing two elements in a collection. To determine if one object should go before or after another, you could define a CallbackFunction interface that has a method that takes 2 things (like int's) and returns a value that indicates which thing should go first. For example,
public interface CallbackForSorting
{
public int compare(int a, int b);
}
public class World
{
List<Integer> thingsToSort;
public void sortThings(CallbackForSorter sorter)
{
int result = sorter.compare(thingsToSort.get(i), thingsToSort.get(i+1));
if(result == 0) // elements are equal
if(result == -1) // thingsToSort.get(i) is "less than" thingsToSort.get(i+1)
if(result == 1) // thingsToSort.get(i) is "greater than" thingsToSort.get(i+1)
}
}

Categories

Resources