studio - Comment déclarer des variables globales dans Android?




variable globale android (12)

Comme il a été discuté ci-dessus OS pourrait tuer l'APPLICATION sans aucune notification (il n'y a pas d'événement onDestroy) donc il n'y a aucun moyen de sauvegarder ces variables globales.

SharedPreferences pourrait être une solution SAUF si vous avez des variables COMPLEX STRUCTURED (dans mon cas j'avais un tableau integer pour stocker les IDs que l'utilisateur a déjà traités). Le problème avec les SharedPreferences est qu'il est difficile de stocker et récupérer ces structures chaque fois que les valeurs nécessaires.

Dans mon cas, j'avais un service en arrière-plan afin que je puisse déplacer ces variables et parce que le service a un événement onDestroy, je pourrais sauvegarder ces valeurs facilement.

Je crée une application qui nécessite une connexion. J'ai créé l'activité principale et l'activité de connexion.

Dans la méthode principale onCreate , j'ai ajouté la condition suivante:

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

    ...

    loadSettings();
    if(strSessionString == null)
    {
        login();
    }
    ...
}

La méthode onActivityResult qui est exécutée lorsque le formulaire de connexion se termine ressemble à ceci:

@Override
public void onActivityResult(int requestCode,
                             int resultCode,
                             Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode)
    {
        case(SHOW_SUBACTICITY_LOGIN):
        {
            if(resultCode == Activity.RESULT_OK)
            {

                strSessionString = data.getStringExtra(Login.SESSIONSTRING);
                connectionAvailable = true;
                strUsername = data.getStringExtra(Login.USERNAME);
            }
        }
    }

Le problème est que le formulaire de connexion apparaît parfois deux fois (la méthode login() est appelée deux fois) et aussi lorsque le clavier du téléphone glisse, le formulaire de connexion réapparaît et je suppose que le problème est la variable strSessionString .

Est-ce que quelqu'un sait comment définir la variable globale afin d'éviter que le formulaire de connexion apparaisse après que l'utilisateur s'est authentifié avec succès?


Créer cette sous-classe

public class MyApp extends Application {
  String foo;
}

Dans AndroidManifest.xml, ajoutez android: nom

Exemple

<application android:name=".MyApp" 
       android:icon="@drawable/icon" 
       android:label="@string/app_name">

Je ne trouvais pas comment spécifier la balise d'application non plus, mais après beaucoup de Google, il est devenu évident à partir du document manifeste docs: use android: name, en plus de l'icône et du label par défaut dans la section application.

android: nom Nom qualifié complet d'une sous-classe Application implémentée pour l'application. Lorsque le processus d'application est démarré, cette classe est instanciée avant l'un des composants de l'application.

La sous-classe est optionnelle; la plupart des applications n'en auront pas besoin. En l'absence de sous-classe, Android utilise une instance de la classe Application de base.


Juste une note ..

ajouter:

android:name=".Globals"

ou tout ce que vous avez nommé votre sous-classe à la <application> existante . J'ai continué à essayer d'ajouter une autre <application> au manifeste et obtenir une exception.


L'approche du sous-classement a également été utilisée par le framework BARACUS. De mon point de vue sous-classe Application a été conçu pour fonctionner avec les cycles de vie d'Android; C'est ce que fait n'importe quel conteneur d'application. Au lieu d'avoir des globals alors, j'inscris des beans dans ce contexte et les laisse être injectés dans n'importe quelle classe gérable par le contexte. Chaque instance de bean injectée est en fait un singleton.

Voir cet exemple pour plus de détails

Pourquoi travailler manuellement si vous pouvez en avoir beaucoup plus?


La méthode proposée par Soonil pour conserver un état pour l'application est bonne, mais elle a un point faible: il y a des cas où le système d'exploitation tue tout le processus de l'application. Voici la documentation sur ce sujet - Processus et cycles de vie .

Considérez un cas - votre application passe en arrière-plan parce que quelqu'un vous appelle (l'application Téléphone est au premier plan maintenant). Dans ce cas && sous certaines autres conditions (vérifiez le lien ci-dessus pour ce qu'ils pourraient être), le système d'exploitation peut tuer votre processus d'application, y compris l'instance de sous-classe Application . En conséquence, l'état est perdu. Lorsque vous revenez plus tard à l'application, le système d'exploitation restaurera sa pile d'activité et l'instance de la sous-classe Application , mais le champ myState sera null .

AFAIK, la seule façon de garantir la sécurité de l'état est d'utiliser une sorte de persistance de l'état, par exemple en utilisant un private pour le fichier d'application ou SharedPrefernces (il utilise finalement un private pour le fichier d'application dans le système de fichiers interne).


Si certaines variables sont stockées dans sqlite, vous devez les utiliser dans la plupart des activités de votre application. alors Application peut-être le meilleur moyen de l'atteindre. Interrogez les variables de la base de données au démarrage de l'application et stockez-les dans un champ. Vous pouvez ensuite utiliser ces variables dans vos activités.

Alors, trouvez le bon chemin, et il n'y a pas de meilleur moyen.


Sur le résultat de l'activité est appelée avant sur le CV. Alors, déplacez votre vérification de connexion à la reprise et votre deuxième connexion peut être bloquée une fois que l'activité secomd a renvoyé un résultat positif. Sur le CV est appelé à chaque fois donc il n'y a pas de soucis de ne pas être appelé la première fois.


Vous pouvez créer une classe qui étend la classe Application , puis déclarer votre variable comme champ de cette classe et lui fournir une méthode getter.

public class MyApplication extends Application {
    private String str = "My String";

    synchronized public String getMyString {
        return str;
    }
}

Et puis pour accéder à cette variable dans votre activité, utilisez ceci:

MyApplication application = (MyApplication) getApplication();
String myVar = application.getMyString();

Vous pouvez le faire en utilisant deux approches:

  1. Utilisation de la classe d'application
  2. Utilisation de préférences partagées

  3. Utilisation de la classe d'application

Exemple:

class SessionManager extends Application{

  String sessionKey;

  setSessionKey(String key){
    this.sessionKey=key;
  }

  String getSessisonKey(){
    return this.sessionKey;
  }
}

Vous pouvez utiliser la classe ci-dessus pour implémenter la connexion dans votre MainActivity comme ci-dessous. Le code ressemblera à ceci:

@override 
public void onCreate (Bundle savedInstanceState){
  // you will this key when first time login is successful.
  SessionManager session= (SessionManager)getApplicationContext();
  String key=getSessisonKey.getKey();
  //Use this key to identify whether session is alive or not.
}

Cette méthode fonctionnera pour le stockage temporaire. Vous n'avez vraiment aucune idée quand le système d'exploitation va tuer l'application, à cause de la mémoire insuffisante. Lorsque votre application est en arrière-plan et que l'utilisateur navigue à travers une autre application qui nécessite plus de mémoire pour s'exécuter, alors votre application sera détruite car le système d'exploitation accorde plus de priorité aux processus de premier plan qu'à l'arrière-plan. Par conséquent, votre objet d'application sera nul avant que l'utilisateur ne se déconnecte. Par conséquent, pour cela, je recommande d'utiliser la deuxième méthode spécifiée ci-dessus.

  1. Utiliser les préférences partagées

    String MYPREF="com.your.application.session"
    
    SharedPreferences pref= context.getSharedPreferences(MyPREF,MODE_PRIVATE);
    
    //Insert key as below:
    
    Editot editor= pref.edit();
    
    editor.putString("key","value");
    
    editor.commit();
    
    //Get key as below.
    
    SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
    
    String key= getResources().getString("key");
    

N'utilisez PAS une autre <application> dans le fichier manifeste. Faites juste une modification dans la <application> existante, ajoutez cette ligne android:name=".ApplicationName" où, ApplicationName sera le nom de votre sous-classe (utilisez pour stocker global ), vous êtes sur le point de créer.

Donc, enfin votre seule et unique étiquette <application> dans le fichier manifeste devrait ressembler à ceci: -

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat.NoActionBar"
        android:name=".ApplicationName"
        >

class GlobaleVariableDemo extends Application {

    private String myGlobalState;

    public String getGlobalState(){
     return myGlobalState;
    }
    public void setGlobalState(String s){
     myGlobalState = s;
    }
}

class Demo extends Activity {

@Override
public void onCreate(Bundle b){
    ...
    GlobaleVariableDemo appState = ((GlobaleVariableDemo)getApplicationContext());
    String state = appState.getGlobalState();
    ...
    }
}




state