Variable that needs to be declared as final

3

Android Studio gives me the following problem:

  

Error: (83, 25) error: local variable btArrayAdapter is accessed from   within inner class; needs to be final final

However, if I put it out of the event of the onclick button, the error is removed.

package net.stackblue_v1_0.stackblue_v1_0;

    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothDevice;
    import android.content.Intent;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.ArrayAdapter;
    import android.widget.Button;
    import android.widget.CompoundButton;
    import android.widget.ListView;
    import android.widget.Switch;
    import android.widget.TextView;
    import android.widget.Toast;

    import java.util.Set;


    public class BluetoothActivity extends AppCompatActivity {

        public BluetoothAdapter mBluetoothAdapter;
        public final static int REQUEST_ENABLE_BT = 1;
        public Switch switch1;
        public Button buttonBD;
        public ListView listViewDE;


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_bluetooth);

            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            switch1 = (Switch) findViewById(R.id.switch1);
            buttonBD = (Button) findViewById(R.id.buttonBD);

            ArrayAdapter<String> btArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);

            listViewDE = (ListView) findViewById(R.id.listViewDE);



            if (mBluetoothAdapter == null) {
                Toast.makeText(getApplicationContext(), "Su dispositivo no soporta bluetooth", Toast.LENGTH_LONG).show();
                switch1.setChecked(false);
            }

            if (mBluetoothAdapter.isEnabled()) {
                Toast.makeText(getApplicationContext(), "El servicio Bluetooth ya estaba activado", Toast.LENGTH_LONG).show();
                switch1.setChecked(true);
            } else {
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
                switch1.setChecked(true);
                }

            switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                    if (isChecked) {
                        mBluetoothAdapter.enable();

                    } else {
                        mBluetoothAdapter.disable();
                    }
                }
            });


            buttonBD.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {

                    Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
                    if (pairedDevices.size() > 0) {
                        // Loop through paired devices
                        Toast.makeText(getApplicationContext(), "Mas de un device", Toast.LENGTH_LONG).show();
                        for (BluetoothDevice device : pairedDevices) {
                            // Add the name and address to an array adapter to show in a ListView
                            btArrayAdapter.add(device.getName() + "\n" + device.getAddress());
                        }
                    }
                    listViewDE.setAdapter(btArrayAdapter);
                }
            });

        }
    }
    
asked by Barkalez 18.04.2016 в 18:39
source

2 answers

3

The problem seems to be in these lines of code:

buttonBD.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {

        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        if (pairedDevices.size() > 0) {
            // Loop through paired devices
            Toast.makeText(getApplicationContext(), "Mas de un device", Toast.LENGTH_LONG).show();
            for (BluetoothDevice device : pairedDevices) {
                // Add the name and address to an array adapter to show in a ListView
                //aquí
                btArrayAdapter.add(device.getName() + "\n" + device.getAddress());
            }
        }
        listViewDE.setAdapter(btArrayAdapter);
    }
});

This happens because the variable btArrayAdapter is a local variable to the method onCreate as shown here:

@Override
protected void onCreate(Bundle savedInstanceState) {
    /* código previo */

    ArrayAdapter<String> btArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);

    /* resto del código */
}

You are using that local variable to the method within an internal class that is local to the method. This is not allowed in Java since the internal class could reinitialize the instance of that variable. To do this, you must mark the variable as type final , as follows:

@Override
protected void onCreate(Bundle savedInstanceState) {
    /* código previo */

    final ArrayAdapter<String> btArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);

    /* resto del código */
}

By marking the variable as type final , the compiler can detect that this variable will be initialized only when it is declared and can not be re-initialized afterwards, ensuring that the problem of possibly reinitializing a local variable to the method does not occur from a local class to the method.

Note that this does not happen with the fields in the class, such as listViewDE .

    
answered by 18.04.2016 в 18:46
0

What is commonly done is to define the variable at the class level:

private ArrayAdapter<String> btArrayAdapter;

within onCreate() you initialize it:

btArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);

and you can use it within OnClickListener of your button.

The other option is to define it as final , as the message suggests

final ArrayAdapter<String> btArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
    
answered by 18.04.2016 в 19:00