Die Existenz einer "Datenbank", auf die jeder, der Android entwickelt, einmal stoßen wird. Wenn Sie SQL bereits berührt haben, ist SQLite eine gute Sache, aber ich bin es nicht. Also beschloss ich, Hilfe von einer Katze zu bekommen, und als ich verschiedene Plug-Ins nachschlug, stieß ich auf "Realm". Es wurde bereits in verschiedenen Apps verwendet und es wurde gesagt, dass es im iOS-Bereich einen gewissen Ruf hat, also habe ich beschlossen, damit zu spielen.
Fügen Sie dem Gradle direkt unter dem Projekt den folgenden Code hinzu.
build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'io.realm:realm-gradle-plugin:3.5.0' //hinzufügen
}
}
Fügen Sie als Nächstes den folgenden Code zum Gradle der App hinzu, für die Sie mit Realm eine Datenbank erstellen möchten.
build.gradle
apply plugin: 'realm-android' //hinzufügen
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' //hinzufügen
}
(Bitte passen Sie die Version usw. jeder Support-Bibliothek an die jeweilige Umgebung an.)
Modellerstellung Das wichtigste Tabellendesign zum Erstellen einer Datenbank. Realm macht es sehr einfach zu entwerfen. Der Beispielcode ist unten dargestellt.
public class Friend extends RealmObject {
@PrimaryKey
private String address; //Adressspalte
private String name; //Namensspalte
// 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; }
}
Ich habe einen String-Typ "Adresse" -Parameter (Spalte) und einen String-Typ "Name" -Parameter (Spalte) in einem Objekt (Datensatz) namens Friend definiert.
Definieren Sie darunter Getter und Setter zum Lesen und Schreiben von Werten in jeder Spalte.
Dieses Mal wollte ich die Adressspalte als Primärschlüssel festlegen, also habe ich die Annotation @ PrimaryKey
hinzugefügt.
Weitere Anmerkungen und ausführliche Erläuterungen finden Sie in der offiziellen Dokumentation.
Die Modellerstellung ist in Realm relativ flexibel, sodass Sie die meisten Dinge tun können, indem Sie immer mehr Anmerkungen und Ihre eigene Methode schreiben.
Indem Sie Ihre eigene Methode schreiben, können Sie auch die Lesbarkeit verbessern, ohne häufig ausgeführte Operationen auf der Controllerseite zu schreiben.
Daten hinzufügen (als Freund registrieren)
```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="Name"
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="Anmeldung"/>
</RelativeLayout>
```
Fügen Sie EditText hinzu, der die Eingabe von Adresse und Name sowie die Schaltfläche zur Bestätigung der Registrierung akzeptiert.
Anzeige der Datenliste (Freundesliste)
```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>
```
Fügen Sie RecyclerView zur Liste hinzu.
```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="Name:"/>
<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>
```
Fügen Sie eine Textansicht hinzu, in der der Name bzw. die Adresse angezeigt werden.
Freund-Bildschirm hinzufügen
```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("Anmeldebestätigung")
.setMessage("Möchten Sie sich als Freund registrieren?")
.setPositiveButton("Ja", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
final Realm realm = Realm.getDefaultInstance(); //Reich instanziieren
final Friend friend = new Friend(); //Instantiate Friend Tabelle
friend.setName(args.getString("name"));
friend.setAddress(args.getString("address"));
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm bgRealm) {
bgRealm.copyToRealmOrUpdate(friend); //Wenn der in PrimaryKey festgelegte Wert bereits vorhanden ist, wird er aktualisiert, andernfalls wird er neu registriert.
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
realm.close(); //Schließen Sie immer, wenn der Datenbankvorgang endet()Lass mich das machen!
Toast.makeText(getContext(), args.getString("name") + "Eingetragen", Toast.LENGTH_SHORT).show();
getActivity().getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); //Fragment schließen
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
realm.close(); //Schließen Sie immer, wenn der Datenbankvorgang endet()Lass mich das machen!
Toast.makeText(getContext(), "Anmeldung gescheitert", Toast.LENGTH_SHORT).show();
}
});
}
})
.setNegativeButton("Nein", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dismiss();
}
});
return builder.create();
}
}
}
```
Die Eingabe von Adresse und Name wird von EditText empfangen und der Wert wird über Bundle an AlertDialog übergeben. Wenn die positive Schaltfläche von AlertDialog gedrückt wird und der Wert der eingegebenen Adresse bereits in der Tabelle vorhanden ist, wird der Name aktualisiert (Aktualisieren), und wenn er nicht vorhanden ist, wird eine neue Registrierung (Einfügen) durchgeführt. .. Ich bin überrascht, dass diese in nur einer Zeile der Realm-Methode "copyToRealmOrUpdate ()" erreicht werden.
Bildschirm der Freundeliste
```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(); //Reich instanziieren
final RealmResults<Friend> result = realm.where(Friend.class).findAll(); //Holen Sie sich alle Datensätze aus der Friend-Tabelle
adapter = new FriendAdapter(result); //Übergeben Sie das Ergebnis an den Adapter
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));
//Implementierter Swipe-Vorgang, der eine Funktion von RecyclerView ist
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) {
//Eigenschaften für jedes Element abrufen
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();
//Die Verarbeitung ist nach der Richtung des Wischens unterteilt
if (direction == ItemTouchHelper.LEFT) { //Element löschen
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(); //Adapter neu zeichnen
Toast.makeText(getContext(), oldName + "Wurde gelöscht", Toast.LENGTH_SHORT).show();
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
adapter.notifyDataSetChanged(); //Adapter neu zeichnen
Toast.makeText(getContext(), "Löschen fehlgeschlagen", Toast.LENGTH_SHORT).show();
}
});
} else { //Elementeigenschaften ändern
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("umbenennen")
.setMessage("Bitte geben Sie den geänderten Namen ein")
.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(); //Adapter neu zeichnen
Toast.makeText(getContext(), oldName + "Herr." + newName + "Umbenannt in", Toast.LENGTH_SHORT).show();
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
adapter.notifyDataSetChanged(); //Adapter neu zeichnen
Toast.makeText(getContext(), "Umbenennen fehlgeschlagen", Toast.LENGTH_SHORT).show();
}
});
}
})
.setNegativeButton("Stornieren", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
})
.create()
.show();
}
}
//Menü wird beim Wischen angezeigt
@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(); //Schließen Sie immer, wenn der Datenbankvorgang endet()Lass mich das machen! }
}
```
In der RecyclerView werden alle Datensätze in der Friend-Tabelle aufgelistet. Wie Sie hier vielleicht bemerkt haben, muss Realm die Daten nicht erneut abrufen, wenn die aus der Tabelle abgerufenen Datensätze aktualisiert oder gelöscht werden. In diesem Code wird der erfasste Datensatz in einer Variablen namens "Ergebnis" gespeichert. Wenn sich jedoch die darin enthaltenen Daten ändern, werden die Daten nacheinander synchronisiert. Es ist wunderbar.
Benutzerdefinierter Adapter
```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);
}
}
}
```
Mit ViewHolder ist es etwas schneller (leichter). Erstellen Sie Ihren eigenen benutzerdefinierten Adapter, der RealmRecyclerViewAdapter <Tabellenname, Adaptername.ViewHolder-Name> erbt.
Tips Ich habe den Code für MainActivity diesmal nicht veröffentlicht, aber Sie müssen Realm mit Activity initialisieren, wenn die App gestartet wird. Ich denke, es ist in Ordnung, wenn Sie den folgenden Code hinzufügen.
Realm.init(this);
RealmConfiguration config = new RealmConfiguration.Builder().build();
Realm.setDefaultConfiguration(config);
Es scheint, dass es verschiedene Parameter für die Konfiguration gibt, also im offiziellen Dokument ...
Nach dem Verteilen der App werden Anfragen wie "Ich möchte eine neue Spalte hinzufügen!", "Ich möchte die Spaltenattribute ändern!" Und "Ich möchte überhaupt eine Tabelle hinzufügen" angezeigt. Realm kann dies mit der Migrationsfunktion erledigen. Wenn es sich jedoch noch in der Entwicklung und vor der Verteilung befindet, ist es schwierig, die Migration einzeln zu beschreiben. Wenn Sie zum Zeitpunkt der Initialisierung den folgenden Code hinzufügen, wird die Datenbank daher einmal sauber gelöscht, sodass keine Migration erforderlich ist.
Realm.deleteRealm(config);
Dies ist nützlich, wenn die Datenbankspezifikationen in den frühen Entwicklungsstadien noch nicht fertiggestellt wurden!
Als ich Realm tatsächlich benutzte, war ich beeindruckt von seiner Benutzerfreundlichkeit. Es ist auch wunderbar, dass die Antwort im Vergleich zu anderen verwandten Plug-Ins überwältigend schnell ist.
Ich denke, es ist perfekt für diejenigen, die SQL noch nie berührt haben und wenig Erfahrung haben. Wenn Sie Probleme mit der von Androi entwickelten Datenbank haben, können Sie sie gerne ausprobieren!
Es gibt Methoden und Funktionen, die noch nicht eingeführt wurden, also im offiziellen Dokument ... Realm Java 3.5.0
Recommended Posts