Android
क्षेत्र
खोज…
परिचय
दायरे मोबाइल डेटाबेस SQLite के लिए एक विकल्प है। दायरे मोबाइल डेटाबेस एक ORM की तुलना में बहुत तेज है, और अक्सर कच्चे SQLite से भी तेज है।
लाभ
ऑफ़लाइन कार्यक्षमता, तेज़ क्वेरी, सुरक्षित थ्रेडिंग, क्रॉस-प्लेटफ़ॉर्म ऐप, एन्क्रिप्शन, रिएक्टिव आर्किटेक्चर।
टिप्पणियों
जब आप Realm का उपयोग करते हैं, तो आपको याद रखना चाहिए कि आप RealmObjects, RealmResults और Realm इंस्टेंस को धागों के बीच से गुजारें। यदि आपको किसी दिए गए थ्रेड पर एक क्वेरी की आवश्यकता है, तो उस थ्रेड पर एक Realm इंस्टेंस खोलें। धागे की समाप्ति पर, आपको दायरे को बंद करना चाहिए।
कानूनी नोट : आप समझते हैं कि सॉफ़्टवेयर में क्रिप्टोग्राफ़िक फ़ंक्शन शामिल हो सकते हैं जो निर्यात प्रतिबंधों के अधीन हो सकते हैं, और आप प्रतिनिधित्व करते हैं और वारंट करते हैं कि आप किसी ऐसे देश में स्थित नहीं हैं , जो क्यूबा, ईरान, उत्तर सहित संयुक्त राज्य अमेरिका के निर्यात प्रतिबंध या प्रतिबंध के अधीन है। कोरिया, सूडान, सीरिया या क्रीमिया क्षेत्र , और यह कि आप डिपार्टमेंट ऑफ़ कॉमर्स लिस्ट ऑफ़ डेनिड पर्सन्स, अनवेरिफाइड पार्टीज़ या एक प्रतिबंधित संस्था से संबद्ध नहीं हैं।
अपने प्रोजेक्ट में दायरे जोड़ना
अपने प्रोजेक्ट स्तर build.gradle
फ़ाइल के लिए निम्न निर्भरता जोड़ें।
dependencies {
classpath "io.realm:realm-gradle-plugin:3.1.2"
}
अपने एप्लिकेशन स्तर build.gradle
फ़ाइल के शीर्ष पर निम्न दाईं ओर जोड़ें।
apply plugin: 'realm-android'
एक सिंक सिंक पूरा करें और आपके पास अब Realm आपके प्रोजेक्ट के लिए एक निर्भरता के रूप में जुड़ गया है!
दायरे का उपयोग करने से पहले 2.0.0 के बाद से एक प्रारंभिक कॉल की आवश्यकता है। आप इसे अपने Application
वर्ग में या अपनी पहली गतिविधि की onCreate
विधि में कर सकते हैं।
Realm.init(this); // added in Realm 2.0.0
Realm.setDefaultConfiguration(new RealmConfiguration.Builder().build());
दायरे के मॉडल
दायरे मॉडल को RealmObject
बेस क्लास का विस्तार करना चाहिए, वे अंतर्निहित डेटाबेस के स्कीमा को परिभाषित करते हैं।
समर्थित फ़ील्ड प्रकार boolean
, byte
, short
, int
, long
, float
, double
, String
, Date
, byte[]
, अन्य RealmObject
s के लिंक, और RealmList<T extends RealmModel>
।
public class Person extends RealmObject {
@PrimaryKey //primary key is also implicitly an @Index
//it is required for `copyToRealmOrUpdate()` to update the object.
private long id;
@Index //index makes queries faster on this field
@Required //prevents `null` value from being inserted
private String name;
private RealmList<Dog> dogs; //->many relationship to Dog
private Person spouse; //->one relationship to Person
@Ignore
private Calendar birthday; //calendars are not supported but can be ignored
// getters, setters
}
यदि आप अपने RealmObject में एक नया फ़ील्ड जोड़ते (या हटाते हैं) या (आप एक नया RealmObject क्लास जोड़ते हैं या किसी मौजूदा को हटाते हैं), तो माइग्रेशन की आवश्यकता होगी। आप या तो अपने RealmConfiguration.Builder
में deleteIfMigrationNeeded()
सेट कर सकते हैं, या आवश्यक माइग्रेशन को परिभाषित कर सकते हैं। @Required
, या @Index
, या @PrimaryKey
एनोटेशन जोड़ते समय (या हटाते समय) माइग्रेशन की भी आवश्यकता होती है।
रिश्तों को मैन्युअल रूप से सेट किया जाना चाहिए, वे प्राथमिक कुंजी के आधार पर स्वचालित नहीं हैं।
0.88.0 के बाद से, RealmObject कक्षाओं में निजी क्षेत्रों / गेटर्स / सेटर के बजाय सार्वजनिक क्षेत्रों का उपयोग करना संभव है।
यदि RealmObject
क्लास को @RealmClass
साथ भी एनोटेट किया गया है, तो RealmObject
को फैलाने के बजाय RealmModel
को लागू करना संभव है।
@RealmClass
public class Person implements RealmModel {
// ...
}
उस स्थिति में, person.deleteFromRealm()
या person.addChangeListener()
जैसे तरीकों को RealmObject.deleteFromRealm(person)
और RealmObject.addChangeListener(person)
साथ बदल दिया जाता है।
सीमाएं यह हैं कि एक RealmObject
द्वारा, केवल RealmObject
को बढ़ाया जा सकता है, और final
, volatile
और transient
क्षेत्रों के लिए कोई समर्थन नहीं है।
यह महत्वपूर्ण है कि एक प्रबंधित RealmObject वर्ग को केवल लेनदेन में ही संशोधित किया जा सकता है। एक प्रबंधित RealmObject थ्रेड्स के बीच पारित नहीं किया जा सकता है।
आदिमों की सूची (RealmList) )
दायरे वर्तमान में आदिम की एक सूची भंडारण का समर्थन नहीं करता है। यह उनकी टूडू सूची ( GitHub अंक # 575 ) पर है, लेकिन इस बीच, यहां एक समाधान है।
अपने आदिम प्रकार के लिए एक नया वर्ग बनाएं, यह इंटेगर का उपयोग करता है, लेकिन जो आप स्टोर करना चाहते हैं, उसके लिए इसे बदल दें।
public class RealmInteger extends RealmObject {
private int val;
public RealmInteger() {
}
public RealmInteger(int val) {
this.val = val;
}
// Getters and setters
}
अब आप इसे अपने RealmObject
में उपयोग कर सकते हैं।
public class MainObject extends RealmObject {
private String name;
private RealmList<RealmInteger> ints;
// Getters and setters
}
आप उपयोग कर रहे हैं GSON
अपने को भरने के लिए RealmObject
, आप एक कस्टम प्रकार एडाप्टर जोड़ने की आवश्यकता होगी।
Type token = new TypeToken<RealmList<RealmInteger>>(){}.getType();
Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getDeclaringClass().equals(RealmObject.class);
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
})
.registerTypeAdapter(token, new TypeAdapter<RealmList<RealmInteger>>() {
@Override
public void write(JsonWriter out, RealmList<RealmInteger> value) throws IOException {
// Empty
}
@Override
public RealmList<RealmInteger> read(JsonReader in) throws IOException {
RealmList<RealmInteger> list = new RealmList<RealmInteger>();
in.beginArray();
while (in.hasNext()) {
list.add(new RealmInteger(in.nextInt()));
}
in.endArray();
return list;
}
})
.create();
कोशिश-साथ-संसाधनों
try (Realm realm = Realm.getDefaultInstance()) {
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
//whatever Transaction that has to be done
}
});
//No need to close realm in try-with-resources
}
संसाधनों के साथ प्रयास केवल KITKAT से उपयोग किया जा सकता है (minSDK 19)
क्रमबद्ध प्रश्न
किसी क्वेरी को सॉर्ट करने के लिए, findAll()
का उपयोग करने के बजाय, आपको findAllSorted()
उपयोग करना चाहिए।
RealmResults<SomeObject> results = realm.where(SomeObject.class)
.findAllSorted("sortField", Sort.ASCENDING);
ध्यान दें:
sort()
एक पूरी तरह से नया RealmResults देता है जिसे क्रमबद्ध किया जाता है, लेकिन इस RealmResults को अपडेट करने से यह रीसेट हो जाएगा। यदि आप sort()
उपयोग करते हैं, तो आपको हमेशा इसे अपने RealmChangeListener
में पुन: सॉर्ट करना चाहिए, पिछले RealmResults
से RealmChangeListener
को RealmResults
और इसे वापस दिए गए नए RealmResults
। RealmResults
पर एक sort()
का उपयोग करके एक async क्वेरी द्वारा लौटाया गया है जो अभी तक लोड नहीं हुआ है।
findAllSorted()
हमेशा फ़ील्ड द्वारा क्रमबद्ध परिणामों को लौटाएगा, भले ही वह अपडेट हो जाए। यह findAllSorted()
का उपयोग करने के लिए अनुशंसित है।
Async प्रश्न
प्रत्येक तुल्यकालिक क्वेरी विधि (जैसे findAll()
या findAllSorted()
) में एक एसिंक्रोनस समकक्ष ( findAllAsync()
/ findAllSortedAsync()
) होता है।
असिंक्रोनस क्वेरीज़ RealmResults
के मूल्यांकन को दूसरे थ्रेड पर RealmResults
करता है। वर्तमान थ्रेड पर ये परिणाम प्राप्त करने के लिए, वर्तमान थ्रेड में लूपर थ्रेड होना चाहिए (पढ़ें: async क्वेरीज़ आमतौर पर केवल UI थ्रेड पर काम करती हैं)।
RealmChangeListener<RealmResults<SomeObject>> realmChangeListener; // field variable
realmChangeListener = new RealmChangeListener<RealmResults<SomeObject>>() {
@Override
public void onChange(RealmResults<SomeObject> element) {
// asyncResults are now loaded
adapter.updateData(element);
}
};
RealmResults<SomeObject> asyncResults = realm.where(SomeObject.class).findAllAsync();
asyncResults.addChangeListener(realmChangeListener);
RxJava के साथ दायरे का उपयोग करना
प्रश्नों के लिए, दायरे realmResults.asObservable()
विधि प्रदान करता है। अवलोकन परिणाम केवल लूपर थ्रेड्स (आमतौर पर UI थ्रेड) पर संभव है।
इस कार्य के लिए, आपके कॉन्फ़िगरेशन में निम्नलिखित शामिल होने चाहिए
realmConfiguration = new RealmConfiguration.Builder(context) //
.rxFactory(new RealmObservableFactory()) //
//...
.build();
बाद में, आप अपने परिणामों को एक अवलोकन के रूप में उपयोग कर सकते हैं।
Observable<RealmResults<SomeObject>> observable = results.asObservable();
अतुल्यकालिक प्रश्नों के लिए, आपको परिणाम को isLoaded()
द्वारा फ़िल्टर करना चाहिए, ताकि आपको केवल एक घटना प्राप्त हो जब क्वेरी निष्पादित की गई हो। यह filter()
तुल्यकालिक प्रश्नों के लिए आवश्यक नहीं है ( isLoaded()
हमेशा सिंक प्रश्नों पर true
)।
Subscription subscription = RxTextView.textChanges(editText).switchMap(charSequence ->
realm.where(SomeObject.class)
.contains("searchField", charSequence.toString(), Case.INSENSITIVE)
.findAllAsync()
.asObservable())
.filter(RealmResults::isLoaded) //
.subscribe(objects -> adapter.updateData(objects));
लिखने के लिए, आपको या तो executeTransactionAsync()
विधि का उपयोग करना चाहिए, या बैकग्राउंड थ्रेड पर एक दायरे का उदाहरण खोलना होगा, लेन-देन को सिंक्रोनाइज़ करना होगा, फिर दायरे को बंद करें।
public Subscription loadObjectsFromNetwork() {
return objectApi.getObjects()
.subscribeOn(Schedulers.io())
.subscribe(response -> {
try(Realm realmInstance = Realm.getDefaultInstance()) {
realmInstance.executeTransaction(realm -> realm.insertOrUpdate(response.objects));
}
});
}
मूल उपयोग
एक उदाहरण स्थापित करना
दायरे का उपयोग करने के लिए आपको सबसे पहले इसका एक उदाहरण प्राप्त करने की आवश्यकता है। प्रत्येक दायरे उदाहरण के लिए डिस्क पर एक फ़ाइल में मैप करता है। एक उदाहरण प्राप्त करने का सबसे मूल तरीका इस प्रकार है:
// Create configuration
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(context).build();
// Obtain realm instance
Realm realm = Realm.getInstance(realmConfiguration);
// or
Realm.setDefaultConfiguration(realmConfiguration);
Realm realm = Realm.getDefaultInstance();
यदि यह नहीं बनाया गया है, तो Realm.getInstance()
डेटाबेस फ़ाइल बनाता है, अन्यथा फ़ाइल को खोलता है। RealmConfiguration
ऑब्जेक्ट सभी पहलुओं को नियंत्रित करता है कि कैसे एक Realm बनाया जाता है - चाहे वह inMemory()
डेटाबेस हो, Realm फ़ाइल का नाम, यदि दायरे की आवश्यकता हो, तो प्रारंभिक डेटा साफ़ किया जाना चाहिए, आदि।
कृपया ध्यान दें कि Realm.getInstance()
कॉल Realm.getInstance()
होते हैं (प्रत्येक कॉल एक काउंटर बढ़ाता है), और काउंटर को तब realm.close()
जाता है जब realm.close()
कहा जाता है।
एक उदाहरण बंद करना
बैकग्राउंड थ्रेड्स पर, रियलम इंस्टेंस को बंद करना बहुत महत्वपूर्ण है, एक बार इसका उपयोग नहीं किया जाता है (उदाहरण के लिए, लेन-देन पूरा हो गया है और थ्रेड निष्पादन समाप्त हो जाता है)। वर्जन पिनिंग में बैकग्राउंड थ्रेड परिणाम पर सभी दायरे को बंद करने में विफलता, और फ़ाइल आकार में बड़ी वृद्धि का कारण बन सकती है।
Runnable runnable = new Runnable() {
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
// ...
} finally {
if(realm != null) {
realm.close();
}
}
};
new Thread(runnable).start(); // background thread, like `doInBackground()` of AsyncTask
यह ध्यान देने योग्य है कि एपीआई स्तर 19 से ऊपर, आप इस कोड को इस से बदल सकते हैं:
try(Realm realm = Realm.getDefaultInstance()) {
// ...
}
मॉडल
अगला कदम अपने मॉडल बनाना होगा। यहां एक प्रश्न पूछा जा सकता है, "एक मॉडल क्या है?"। एक मॉडल एक संरचना है जो डेटाबेस में संग्रहीत किसी वस्तु के गुणों को परिभाषित करता है। उदाहरण के लिए, निम्नलिखित में हम एक पुस्तक का मॉडल बनाते हैं।
public class Book extends RealmObject {
// Primary key of this entity
@PrimaryKey
private long id;
private String title;
@Index // faster queries
private String author;
// Standard getters & setter
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
ध्यान दें कि आपके मॉडल को RealmObject क्लास का विस्तार करना चाहिए। प्राथमिक कुंजी @PrimaryKey
एनोटेशन द्वारा भी निर्दिष्ट की गई है। प्राथमिक कुंजी शून्य हो सकती है, लेकिन प्राथमिक कुंजी के रूप में केवल एक तत्व null
हो सकता है। साथ ही आप उन फ़ील्ड्स के लिए @Ignore
एनोटेशन का उपयोग कर सकते हैं, @Ignore
डिस्क पर नहीं होना चाहिए:
@Ignore
private String isbn;
डेटा डालना या अपडेट करना
अपने दायरे डेटाबेस उदाहरण के लिए एक पुस्तक ऑब्जेक्ट को संग्रहीत करने के लिए, आप पहले अपने मॉडल का एक उदाहरण बना सकते हैं और फिर इसे copyToRealm
विधि के माध्यम से डेटाबेस में संग्रहीत कर सकते हैं। बनाने या अपडेट करने के लिए आप copyToRealmOrUpdate
उपयोग कर सकते हैं। (एक तेज विकल्प नव जोड़ा insertOrUpdate()
)।
// Creating an instance of the model
Book book = new Book();
book.setId(1);
book.setTitle("Walking on air");
book.setAuthor("Taylor Swift")
// Store to the database
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.insertOrUpdate(book);
}
});
ध्यान दें कि डेटा में सभी परिवर्तन लेनदेन में होने चाहिए। ऑब्जेक्ट बनाने का दूसरा तरीका निम्नलिखित पैटर्न का उपयोग कर रहा है:
Book book = realm.createObject(Book.class, primaryKey);
...
डेटाबेस को छोड़ना
सभी पुस्तकें:
RealmResults<Book> results = realm.where(Book.class).findAll();
10 से अधिक आईडी वाली सभी पुस्तकें:
RealmResults<Book> results = realm.where(Book.class) .greaterThan("id", 10) .findAll();
'Taylor Swift'
या'%Peter%'
पुस्तकें:RealmResults<Book> results = realm.where(Book.class) .beginGroup() .equalTo("author", "Taylor Swift") .or() .contains("author", "Peter") .endGroup().findAll();
किसी वस्तु को हटाना
उदाहरण के लिए, हम टेलर स्विफ्ट की सभी पुस्तकों को हटाना चाहते हैं:
// Start of transaction
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
// First Step: Query all Taylor Swift books
RealmResults<Book> results = ...
// Second Step: Delete elements in Realm
results.deleteAllFromRealm();
}
});