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