Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
111 views
in Technique[技术] by (71.8m points)

java - Android execute code on variable change

I alter a variable on different button clicks, (i.e. inside the onclick listener for multiple buttons) and I have a textview that is suppose to show this variable, but remains outside the listener code.

The textview doesnt update the variable, so I am thinking i possibly need an 'onclick' handler version for variables.

How would I go about doing this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There is no way in Java to be notified when a variable or class field changes. What you need to do is to implement a simple wrapper class for your int so that clients can register for callbacks whenever the value changes. This class might look something like this:

package com.example.android;

/**
 * A store of an int value. You can register a listener that will be notified
 * when the value changes.
 */
public class IntValueStore {

    /**
     * The current value.
     */
    int mValue;

    /**
     * The listener (you might want turn this into an array to support many
     * listeners)
     */
    private IntValueStoreListener mListener;

    /**
     * Construct a the int store.
     *
     * @param initialValue The initial value.
     */
    public IntValueStore(int initialValue) {
        mValue = initialValue;
    }

    /**
     * Sets a listener on the store. The listener will be modified when the
     * value changes.
     *
     * @param listener The {@link IntValueStoreListener}.
     */
    public void setListener(IntValueStoreListener listener) {
        mListener = listener;
    }

    /**
     * Set a new int value.
     *
     * @param newValue The new value.
     */
    public void setValue(int newValue) {
        mValue = newValue;
        if (mListener != null) {
            mListener.onValueChanged(mValue);
        }
    }

    /**
     * Get the current value.
     *
     * @return The current int value.
     */
    public int getValue() {
        return mValue;
    }

    /**
     * Callbacks by {@link IntValueModel}.
     */
    public static interface IntValueStoreListener {
        /**
         * Called when the value of the int changes.
         *
         * @param newValue The new value.
         */
        void onValueChanged(int newValue);
    }
}

Now you need to have some class that implements the IntValueStoreListener interface. You could let that be the Activity, which would then keep track of a TextView to update. I would implement a trivial custom TextView instead, like this:

package com.example.android;

import com.example.android.IntValueStore.IntValueStoreListener;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;

public class IntTextView extends TextView implements IntValueStoreListener{

    public IntTextView(Context context) {
        super(context);
    }

    public IntTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void onValueChanged(int newValue) {
        // The int got a new value! Update the text
        setText(String.valueOf(newValue));
    }
}

You can now setup your layout XML. For example:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/btn_increment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Increment" />

    <Button
        android:id="@+id/btn_double"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Double" />

    <com.example.android.IntTextView
        android:id="@+id/text_current_value"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

An activity that does the necessary setup would look like this:

package com.example.android;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;

public class IntValueStoreActivity extends Activity {

    private IntValueStore mIntValueModel = new IntValueStore(1);

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Initialize the text view with the initial value
        IntTextView intTextView = (IntTextView)findViewById(R.id.text_current_value);
        intTextView.setText(String.valueOf(mIntValueModel.getValue()));

        // Setup the text view as a listener so it gets updated whenever the int
        // value changes
        mIntValueModel.setListener(intTextView);

        // Setup an OnClickListener that will increment the int value by 1. The
        // TextView will be automatically updated since it is setup as a
        // listener to the int value store
        findViewById(R.id.btn_increment).setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                mIntValueModel.setValue(mIntValueModel.getValue() + 1);
            }
        });

        // Setup an OnClickListener that will double the int value. The TextView
        // will be automatically updated since it is setup as a listener to the
        // int value store
        findViewById(R.id.btn_double).setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                mIntValueModel.setValue(mIntValueModel.getValue() * 2);
            }
        });
    }
}

This will give you the following UI:

App screenshot

Whenever you click any of the buttons, the TextView will almost magically update the value it displays, even though none of the OnClickListeners have any code to touch the TextView!

This is actually a common pattern in programming called Model-view-controller. In the sample code above, the Model is IntValueStore and the View is IntTextView and there is no Controller.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...