Donc, le titre dit tout. Je reçois une erreur de compilation à l'intérieur de mon onClick
.
Voici le code.
public class fieldsActivity extends Activity {
Button addSiteButton;
Button cancelButton;
Button signInButton;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// to create a custom title bar for activity window
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.fields);
// use custom layout title bar
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.topbar);
Pager adapter = new Pager();
ViewPager mPager = (ViewPager) findViewById(R.id.fieldspager);
mPager.setAdapter(adapter);
mPager.setCurrentItem(1);
addSiteButton = (Button) findViewById(R.id.addSiteButton);
addSiteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPager.setCurrentItem(2, true); //Compilation error happens here.
}
});
cancelButton = (Button) findViewById(R.id.cancel_button);
signInButton = (Button) findViewById(R.id.sign_in_button);
}
Si vous ne voulez pas le rendre final, vous pouvez toujours en faire une variable globale.
Vous pouvez déclarer la variable finale ou en faire une variable d'instance (ou globale). Si vous le déclarez final, vous ne pourrez pas le changer plus tard.
Toute variable définie dans une méthode et accessible par une classe interne anonyme doit être finale. Sinon, vous pouvez utiliser cette variable dans la classe interne, sans savoir que si la variable change dans la classe interne et qu'elle est utilisée ultérieurement dans la portée englobante, les modifications apportées à la classe interne ne sont pas persistantes dans la portée englobante. Fondamentalement, ce qui se passe dans la classe interne reste dans la classe interne.
J'ai écrit un plus explication détaillée ici . Cela explique également pourquoi les variables d'instance et globales n'ont pas besoin d'être déclarées finales.
L'erreur dit tout, change:
ViewPager mPager = (ViewPager) findViewById(R.id.fieldspager);
à
final ViewPager mPager = (ViewPager) findViewById(R.id.fieldspager);
Voici une réponse amusante.
Vous pouvez déclarer un tableau final à un élément et modifier les éléments du tableau tout ce que vous voulez apparemment. Je suis sûr que cela brise la raison même pour laquelle cette règle du compilateur a été implémentée, mais c'est pratique lorsque vous êtes dans une contrainte de temps comme j'étais aujourd'hui.
En fait, je ne peux pas demander de crédit pour celui-ci. C'était la recommandation de IntelliJ! Se sent un peu hacky. Mais cela ne semble pas aussi grave qu’une variable globale, j’ai donc pensé que cela méritait d’être mentionné ici. Ce n'est qu'une solution au problème. Pas nécessairement le meilleur.
final int[] tapCount = {0};
addSiteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tapCount[0]++;
}
});
Comme @Veger l'a dit, vous pouvez le rendre final
afin que la variable puisse être utilisée dans la classe interne.
final ViewPager pager = (ViewPager) findViewById(R.id.fieldspager);
Je l'ai appelé pager
plutôt que mPager
parce que vous l'utilisez comme variable locale dans la méthode onCreate
. Le préfixe m
est réservé de manière personnalisée aux variables de membre de classe (c'est-à-dire aux variables déclarées au début de la classe et disponibles pour toutes les méthodes de classe).
Si vous avez réellement besoin d'une variable de membre de classe, cela ne fonctionnera pas pour la rendre finale car vous ne pouvez pas utiliser findViewById
pour définir sa valeur tant que onCreate
. La solution consiste à ne pas utiliser une classe interne anonyme. De cette manière, la variable mPager
n'a pas besoin d'être déclarée finale et peut être utilisée dans toute la classe.
public class MainActivity extends AppCompatActivity {
private ViewPager mPager;
private Button mButton;
@Override
public void onCreate(Bundle savedInstanceState) {
// ...
mPager = (ViewPager) findViewById(R.id.fieldspager);
// ...
mButton.setOnClickListener(myButtonClickHandler);
}
View.OnClickListener myButtonClickHandler = new View.OnClickListener() {
@Override
public void onClick(View view) {
mPager.setCurrentItem(2, true);
}
};
}