L'existence d'une "base de données" que toute personne développant Android rencontrera une fois. Si vous avez déjà touché SQL, SQLite est une bonne chose, mais je ne le suis pas. J'ai donc décidé de me faire aider par un chat, et quand j'ai recherché divers plug-ins, je suis tombé sur "Realm". Il a déjà été utilisé dans diverses applications, et on a dit qu'il avait une certaine réputation dans le domaine iOS, j'ai donc décidé de jouer avec.

Ajoutez le code suivant au gradle directement sous le projet.
build.gradle
buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:2.3.3'
    classpath 'io.realm:realm-gradle-plugin:3.5.0' //ajouter à
  }
}
Ensuite, ajoutez le code suivant au gradle de l'application pour laquelle vous souhaitez créer une base de données à l'aide de Realm.
build.gradle
apply plugin: 'realm-android' //ajouter à
dependencies {
  compile fileTree(include: ['*.jar'], dir: 'libs')
  compile 'com.android.support:appcompat-v7:26.0.0-alpha1'
  compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'
  compile 'com.android.support:support-v4:26.0.0-alpha1'
  compile 'io.realm:android-adapters:2.1.0' //ajouter à
}
(Veuillez ajuster la version etc. de chaque bibliothèque de support en fonction de chaque environnement.)
Création de modèles La conception de table la plus importante pour la construction d'une base de données. Realm facilite la conception. L'exemple de code est illustré ci-dessous.
public class Friend extends RealmObject {
  @PrimaryKey
  private String address;  //colonne d'adresse
  private String name;  //colonne de nom
  // getter setter...
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
  public String getAddress() { return address; }
  public void setAddress(String address) { this.address = address; }
}
J'ai défini un paramètre de type String "adresse" (colonne) et un paramètre de type chaîne "nom" (colonne) dans un objet (enregistrement) appelé Friend.
En dessous, définissez les Getters et les Setters pour lire et écrire les valeurs dans chaque colonne.
Cette fois, je voulais définir la colonne d'adresse comme clé primaire, j'ai donc ajouté l'annotation @ PrimaryKey.
D'autres annotations et explications détaillées peuvent être trouvées dans la documentation officielle. 
La création de modèle est relativement flexible dans Realm, vous pouvez donc faire la plupart des choses en écrivant de plus en plus d'annotations et votre propre méthode.
De plus, en écrivant votre propre méthode, vous pouvez améliorer la lisibilité sans écrire les opérations fréquemment effectuées du côté du contrôleur.
Afficher la création Nous allons créer un exemple d'écran pour ajouter des données au modèle (table Friend) créé précédemment et un écran pour afficher une liste. --Ajouter des données (s'inscrire comme ami)
```fragment_addfriend.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/White"
            tools:context=".AddFriendFragment">
  <EditText
    android:id="@+id/address_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="30dp"
    android:ems="12"
    android:hint="adresse"
    android:inputType="text"
    android:maxLines="1"/>
  <EditText
    android:id="@+id/name_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/address_text"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="10dp"
    android:ems="12"
    android:hint="Nom"
    android:inputType="text"
    android:maxLines="1"/>
  <Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/name_text"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="30dp"
    android:text="enregistrement"/>
</RelativeLayout>
```
Ajoutez EditText qui accepte l'entrée de l'adresse et du nom et le bouton de la boîte de dialogue de confirmation d'enregistrement.
Affichage de la liste de données (liste d'amis)
 ```fragment_friendlist.xml
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:background="@color/White"
             tools:context=".FriendListFragment">
 
   <android.support.v7.widget.RecyclerView
     android:id="@+id/friend_list"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_below="@+id/button"/>
 
 </FrameLayout>
 ```
Ajoutez RecyclerView à la liste.
    ```row_friend.xml
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dp">
    
      <TextView
        android:id="@+id/label1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Nom:"/>
    
      <TextView
        android:id="@+id/name_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/label1"
        android:layout_toEndOf="@+id/label1"/>
    
      <TextView
        android:id="@+id/label2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignStart="@+id/label1"
        android:layout_below="@+id/label1"
        android:layout_marginTop="10dp"
        android:text="adresse:"/>
    
      <TextView
        android:id="@+id/address_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/label2"
        android:layout_toEndOf="@+id/label2"/>
    
    </RelativeLayout>
    ```
Ajoutez un TextView qui affiche respectivement le nom et l'adresse.
Ajouter un écran ami
 ```AddFriendFragment.java
 public class AddFriendFragment extends Fragment {
   private EditText addressText;
   private EditText nameText;
   private Button mButton;
 
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.fragment_forth, container, false);
 
     addressText = view.findViewById(R.id.address_text);
     nameText = view.findViewById(R.id.name_text);
     mButton = view.findViewById(R.id.button);
   
     return view;
   }
 
   @Override
   public void onStart() {
     super.onStart();
 
     mButton.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
         DialogFragment friendRegisterDialog = new FriendRegisterDialog();
         Bundle args = new Bundle();
         args.putString("name", nameText.getText().toString());
         args.putString("address", addressText.getText().toString());
         friendRegisterDialog.setArguments(args);
         friendRegisterDialog.show(getActivity().getSupportFragmentManager(), "friendRegister");
       }
     });
   }
 
   public static class FriendRegisterDialog extends DialogFragment {
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
       final Bundle args = getArguments();
       AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
       builder.setTitle("Confirmation d'enregistrement")
               .setMessage("Voulez-vous vous inscrire en tant qu'ami?")
               .setPositiveButton("Oui", new DialogInterface.OnClickListener() {
                 public void onClick(DialogInterface dialog, int id) {
                   final Realm realm = Realm.getDefaultInstance();  //Instancier le royaume
                   final Friend friend = new Friend();  //Instancier la table des amis
                   friend.setName(args.getString("name"));
                   friend.setAddress(args.getString("address"));
                   realm.executeTransactionAsync(new Realm.Transaction() {
                     @Override
                     public void execute(Realm bgRealm) {
                       bgRealm.copyToRealmOrUpdate(friend);  //Si la valeur définie dans PrimaryKey existe déjà, elle sera mise à jour, sinon elle sera nouvellement enregistrée.
                     }
                   }, new Realm.Transaction.OnSuccess() {
                     @Override
                     public void onSuccess() {
                       realm.close();  //Toujours fermer lorsque l'opération de base de données se termine()Laisse moi faire!
                       Toast.makeText(getContext(), args.getString("name") + "Inscrit", Toast.LENGTH_SHORT).show();
                       getActivity().getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); //Fermer le fragment
                     }
                   }, new Realm.Transaction.OnError() {
                     @Override
                     public void onError(Throwable error) {
                       realm.close();  //Toujours fermer lorsque l'opération de base de données se termine()Laisse moi faire!
                       Toast.makeText(getContext(), "Inscription échouée", Toast.LENGTH_SHORT).show();
                     }
                   });
                 }
               })
               .setNegativeButton("Non", new DialogInterface.OnClickListener() {
                 public void onClick(DialogInterface dialog, int id) {
                   dismiss();
                 }
               });
       return builder.create();
     }
   }
 }
 ```
L'adresse et le nom saisis sont reçus par EditText et la valeur est transmise à AlertDialog via Bundle. Et lorsque le bouton positif de AlertDialog est pressé, si la valeur de l'adresse saisie existe déjà sur la table, le nom est mis à jour (Update), et s'il n'existe pas, un nouvel enregistrement (Insert) est effectué. ..
Je suis surpris que ceux-ci soient atteints en une seule ligne de la méthode de Realm copyToRealmOrUpdate ().
Écran de la liste d'amis
 ```FriendListFragment.java
 public class FriendListFragment extends Fragment {
   private RecyclerView mRecyclerView;
   private FriendAdapter adapter;
   private Realm realm;
 
   @Override
   public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.fragment_fifth, container, false);
 
     realm = Realm.getDefaultInstance(); //Instancier le royaume
     final RealmResults<Friend> result = realm.where(Friend.class).findAll(); //Obtenir tous les enregistrements de la table Friend
     adapter = new FriendAdapter(result); //Transmettez le résultat à l'adaptateur
 
     mRecyclerView = view.findViewById(R.id.friend_list);
     mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
     mRecyclerView.setAdapter(adapter);
     mRecyclerView.setHasFixedSize(true);
     mRecyclerView.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));
 
     //Mise en œuvre de l'opération de balayage, qui est une fonctionnalité de RecyclerView
     ItemTouchHelper touchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
       @Override
       public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
         return false;
       }
 
       @Override
       public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) {
         //Obtenir les propriétés de chaque élément
         TextView nameText = viewHolder.itemView.findViewById(R.id.name_text);
         TextView address_text = viewHolder.itemView.findViewById(R.id.address_text);
         final String oldName = nameText.getText().toString();
         final String address = address_text.getText().toString();
 
         //Le traitement est divisé en fonction de la direction du balayage
         if (direction == ItemTouchHelper.LEFT) { //Effacer l'article
           realm.executeTransactionAsync(new Realm.Transaction() {
             @Override
             public void execute(Realm bgRealm) {
               Friend obj = bgRealm.where(Friend.class).equalTo("address", address).findFirst();
               obj.deleteFromRealm();
             }
           }, new Realm.Transaction.OnSuccess() {
             @Override
             public void onSuccess() {
               adapter.notifyDataSetChanged();  //Redessiner l'adaptateur
               Toast.makeText(getContext(), oldName + "A été supprimée", Toast.LENGTH_SHORT).show();
             }
           }, new Realm.Transaction.OnError() {
             @Override
             public void onError(Throwable error) {
               adapter.notifyDataSetChanged();  //Redessiner l'adaptateur
               Toast.makeText(getContext(), "Échec de la suppression", Toast.LENGTH_SHORT).show();
             }
           });
         } else { //Modifier les propriétés de l'élément
           final EditText input = new EditText(getContext());
           input.setInputType(TYPE_CLASS_TEXT);
           input.setMaxLines(1);
           input.setText(oldName);
           AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
           builder.setTitle("Renommer")
                   .setMessage("Veuillez saisir le nom modifié")
                   .setView(input)
                   .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int id) {
                       final String newName = input.getText().toString();
                       final Friend friend = new Friend();
                       friend.setName(newName);
                       friend.setAddress(address);
                       realm.executeTransactionAsync(new Realm.Transaction() {
                         @Override
                         public void execute(Realm bgRealm) {
                           bgRealm.copyToRealmOrUpdate(friend);
                         }
                       }, new Realm.Transaction.OnSuccess() {
                         @Override
                         public void onSuccess() {
                           adapter.notifyDataSetChanged();  //Redessiner l'adaptateur
                           Toast.makeText(getContext(), oldName + "M." + newName + "Renommé en", Toast.LENGTH_SHORT).show();
                         }
                       }, new Realm.Transaction.OnError() {
                         @Override
                         public void onError(Throwable error) {
                           adapter.notifyDataSetChanged();  //Redessiner l'adaptateur
                           Toast.makeText(getContext(), "Renommer a échoué", Toast.LENGTH_SHORT).show();
                         }
                       });
                     }
                   })
                   .setNegativeButton("Annuler", new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int whichButton) {
                     }
                   })
                   .create()
                   .show();
         }
       }
 
       //Menu affiché lors du balayage
       @Override
       public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
         if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
           Bitmap icon;
           Paint p = new Paint();
           View itemView = viewHolder.itemView;
           float height = (float) itemView.getBottom() - (float) itemView.getTop();
           float width = height / 3;
 
           if (dX > 0) {
             p.setColor(Color.parseColor("#388E3C"));
             RectF background = new RectF((float) itemView.getLeft(), (float) itemView.getTop(), dX, (float) itemView.getBottom());
             c.drawRect(background, p);
             icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
             RectF icon_dest = new RectF((float) itemView.getLeft() + width, (float) itemView.getTop() + width, (float) itemView.getLeft() + 2 * width, (float) itemView.getBottom() - width);
             if (dX > itemView.getLeft() + icon.getWidth()) {
               c.drawBitmap(icon, null, icon_dest, p);
             }
           } else if (dX < 0) {
             p.setColor(Color.parseColor("#D32F2F"));
             RectF background = new RectF((float) itemView.getRight() + dX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom());
             c.drawRect(background, p);
             icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
             RectF icon_dest = new RectF((float) itemView.getRight() - 2 * width, (float) itemView.getTop() + width, (float) itemView.getRight() - width, (float) itemView.getBottom() - width);
             if (dX < -(itemView.getLeft() + icon.getWidth())) {
               c.drawBitmap(icon, null, icon_dest, p);
             }
           }
         }
         super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
       }
     });
     touchHelper.attachToRecyclerView(mRecyclerView);
 
     return view;
   }
 
   @Override
public void onDestroy() { super.onDestroy(); mRecyclerView.setAdapter(null); realm.close(); //Toujours fermer lorsque l'opération de base de données se termine()Laisse moi faire! }
 }
 ```
Le RecyclerView répertorie tous les enregistrements de la table Friend. Comme vous l'avez peut-être remarqué ici, Realm n'a pas besoin de récupérer à nouveau les données lorsque les enregistrements extraits de la table sont mis à jour ou supprimés. Dans ce code, l'enregistrement acquis est stocké dans une variable appelée «résultat», mais s'il y a un changement dans les données qu'il contient, les données seront synchronisées séquentiellement. C'est merveilleux. --Adaptateur personnalisé
    ```FriendAdapter.java
    class FriendAdapter extends RealmRecyclerViewAdapter<Friend, FriendAdapter.FriendViewHolder> {
      private OrderedRealmCollection<Friend> objects;
    
      FriendAdapter(OrderedRealmCollection<Friend> friends) {
        super(friends, true);
        this.objects = friends;
        setHasStableIds(true);
      }
    
      @Override
      public FriendViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_friend, parent, false);
        return new FriendViewHolder(view);
      }
    
      @Override
      public void onBindViewHolder(FriendViewHolder holder, int position) {
        final Friend obj = getItem(position);
        //noinspection ConstantConditions
        holder.name.setText(obj.getName());
        holder.address.setText(obj.getAddress());
      }
    
      @Override
      public int getItemCount() {
        return objects.size();
      }
    
      static class FriendViewHolder extends RecyclerView.ViewHolder {
        TextView name;
        TextView address;
    
        FriendViewHolder(View view) {
          super(view);
          name = view.findViewById(R.id.name_text);
          address = view.findViewById(R.id.address_text);
        }
      }
    }
    ```
C'est un peu plus rapide (plus léger) en utilisant ViewHolder. Créez votre propre adaptateur personnalisé qui hérite de RealmRecyclerViewAdapter <nom de la table, nom de l'adaptateur.Nom de ViewHolder>.
Tips Je n'ai pas publié le code pour MainActivity cette fois, mais vous devez initialiser Realm avec Activity lorsque l'application démarre. Je pense que ce n'est pas grave si vous ajoutez le code suivant.
Realm.init(this);
RealmConfiguration config = new RealmConfiguration.Builder().build();
Realm.setDefaultConfiguration(config);
Il semble qu'il existe différents paramètres de configuration, donc dans le document officiel ...
De plus, après la distribution de l'application, il y aura des demandes telles que "Je veux ajouter une nouvelle colonne!", "Je veux changer les attributs de colonne!", Et "Je veux ajouter une table en premier lieu". Realm peut gérer cela avec la fonction de migration. Cependant, s'il est encore en cours de développement et avant distribution, il est difficile de décrire la migration une par une. Par conséquent, si vous ajoutez le code suivant au moment de l'initialisation, la base de données sera supprimée une fois proprement, la migration n'est donc pas nécessaire.
Realm.deleteRealm(config);
Ceci est utile lorsque les spécifications de la base de données n'ont pas été finalisées au tout début du développement!
Lorsque j'ai utilisé Realm, j'ai été impressionné par sa facilité d'utilisation. Il est également merveilleux que la réponse soit extrêmement rapide par rapport à d'autres plug-ins associés.
Je pense que c'est parfait pour ceux qui n'ont jamais touché à SQL et qui ont peu d'expérience. Si vous rencontrez des problèmes avec la base de données développée par Androi, n'hésitez pas à l'essayer!
Il y a des méthodes et des fonctions qui n'ont pas encore été introduites, donc dans le document officiel ... Realm Java 3.5.0
Recommended Posts