खास तौर पर ऑफ़लाइन ऐप्लिकेशन बनाएं

ऑफ़लाइन मोड में इस्तेमाल किया जाने वाला ऐप्लिकेशन, ऐसा ऐप्लिकेशन होता है जो सभी या कुछ ज़रूरी सबसेट कर सकता है और इसके मुख्य फ़ंक्शन को इंटरनेट की सुविधा के बिना भी इस्तेमाल किया जा सकता है. इसका मतलब है कि यह काम अपने कुछ या सभी कारोबारी नियम ऑफ़लाइन परफ़ॉर्म करते हैं.

डेटा लेयर में, ऑफ़लाइन ऐप्लिकेशन का इस्तेमाल शुरू करने से पहले ध्यान देने वाली बातें इसकी मदद से, ऐप्लिकेशन के डेटा और कारोबारी नियम को ऐक्सेस किया जा सकता है. ऐप्लिकेशन को ये काम करने पड़ सकते हैं इससे डेटा को समय-समय पर रीफ़्रेश किया जा सकता है. तय सीमा में ऐसा करने पर, हो सकता है कि उसे अप-टू-डेट रहने के लिए नेटवर्क संसाधनों को कॉल करने की ज़रूरत पड़े.

नेटवर्क उपलब्ध होने की हमेशा गारंटी नहीं होती है. आम तौर पर, डिवाइसों में खराब या धीमा इंटरनेट कनेक्शन. उपयोगकर्ताओं को ये अनुभव हो सकते हैं:

  • इंटरनेट की सीमित बैंडविथ
  • ट्रांज़िट में आने वाली रुकावटें, जैसे कि लिफ़्ट में या टनल.
  • समय-समय पर डेटा का ऐक्सेस. उदाहरण के लिए, सिर्फ़ वाई-फ़ाई वाले टैबलेट.

इन वजहों के बावजूद, ऐसा हो सकता है कि कोई ऐप्लिकेशन सही तरीके से काम करे आपके पास इन मामलों में. यह पक्का करने के लिए कि आपका ऐप्लिकेशन ऑफ़लाइन तरीके से काम करे, इसके लिए ज़रूरी है:

  • भरोसेमंद इंटरनेट कनेक्शन के बिना भी इस्तेमाल किया जा सकता है.
  • उपयोगकर्ताओं को पहले डेटा का इंतज़ार करने के बजाय, उसे तुरंत लोकल डेटा उपलब्ध कराएं नेटवर्क कॉल पूरा करने या न हो पाने के लिए.
  • डेटा को इस तरीके से फ़ेच करें जो बैटरी और डेटा की स्थिति के हिसाब से हो. इसके लिए उदाहरण के लिए, सिर्फ़ सबसे सही स्थितियों में डेटा फ़ेच करने का अनुरोध करना. जैसे चार्ज करते समय या WiFi पर उपयोग करते समय.

जो ऐप्लिकेशन ऊपर दी गई शर्तों को पूरा करता है उसे आम तौर पर, ऑफ़लाइन ऐप्लिकेशन कहा जाता है.

पहले ऑफ़लाइन ऐप्लिकेशन डिज़ाइन करें

ऑफ़लाइन ऐप्लिकेशन को डिज़ाइन करते समय, आपको डेटा लेयर से शुरू करना चाहिए और ऐप्लिकेशन के डेटा का इस्तेमाल करने के लिए, ये दो मुख्य काम किए जा सकते हैं:

  • पढ़ने का ऐक्सेस: ऐप्लिकेशन के अन्य हिस्सों में इस्तेमाल करने के लिए डेटा वापस पाना. जैसे, ऐप्लिकेशन दिखाना उपयोगकर्ता को जानकारी देते हैं.
  • लिखना: बाद में वापस लाने के लिए उपयोगकर्ता के इनपुट को बनाए रखना.

डेटा लेयर में मौजूद डेटा स्टोर करने की जगहें, डेटा सोर्स को मिलाने के लिए ज़िम्मेदार होती हैं ऐप्लिकेशन का डेटा उपलब्ध कराने के लिए. ऑफ़लाइन मोड में इस्तेमाल किए जाने वाले ऐप्लिकेशन में, कम से कम एक डेटा होना चाहिए जिसे अपने सबसे अहम काम करने के लिए, नेटवर्क के ऐक्सेस की ज़रूरत नहीं होती. एक में से एक अहम टास्क, डेटा को पढ़ने का होता है.

ऑफ़लाइन-फ़र्स्ट ऐप्लिकेशन में डेटा मॉडल करें

ऑफ़लाइन होने पर इस्तेमाल किए जाने वाले ऐप्लिकेशन में, कम से कम दो डेटा सोर्स होने चाहिए, ताकि हर डेटा स्टोर में नेटवर्क संसाधनों का इस्तेमाल किया जाता है:

  • स्थानीय डेटा सोर्स
  • नेटवर्क का डेटा सोर्स
ऑफ़लाइन-फ़र्स्ट डेटा लेयर में लोकल और नेटवर्क, दोनों के डेटा सोर्स होते हैं
पहली इमेज: डेटा स्टोर करने की ऑफ़लाइन जगह

स्थानीय डेटा सोर्स

स्थानीय डेटा सोर्स, ऐप्लिकेशन के लिए सही स्रोत होता है. यह उस डेटा का खास सोर्स होना चाहिए जिसे ऐप्लिकेशन की बड़ी लेयर के लिए पढ़ा जाता है. इससे यह पक्का किया जाता है कि कनेक्शन की स्थितियों के बीच डेटा एक जैसा हो. स्थानीय डेटा डेटा सोर्स में अक्सर उस स्टोरेज का इस्तेमाल होता है जो डिस्क में सेव रहता है. कुछ सामान्य तरीके ये हैं:

  • स्ट्रक्चर्ड डेटा सोर्स, जैसे कि रूम जैसे रिलेशनल डेटाबेस.
  • अनस्ट्रक्चर्ड डेटा सोर्स. उदाहरण के लिए, Datastore के साथ प्रोटोकॉल बफ़र होता है.
  • सिंपल फ़ाइलें

नेटवर्क का डेटा सोर्स

ऐप्लिकेशन की असल स्थिति, नेटवर्क डेटा सोर्स होती है. स्थानीय डेटा स्रोत, नेटवर्क डेटा स्रोत के साथ सबसे अच्छी तरह सिंक किया हुआ हो. वीडियो में देरी भी हो सकती है के पीछे होता है, इस स्थिति में ऐप्लिकेशन को वापस ऑनलाइन होने पर अपडेट करने की ज़रूरत होगी. इसके उलट, नेटवर्क डेटा सोर्स तब तक लोकल डेटा सोर्स से पीछे हो सकता है कनेक्टिविटी वापस आने पर, ऐप्लिकेशन इसे अपडेट कर सकता है. इसके डोमेन और यूज़र इंटरफ़ेस (यूआई) लेयर ऐप्लिकेशन को कभी भी सीधे नेटवर्क लेयर से संपर्क नहीं करना चाहिए. यह है repository को होस्ट करने की ज़िम्मेदारी है कि वह उनसे संपर्क करे और लोकल डेटा सोर्स अपडेट करें.

संसाधनों को सार्वजनिक करना

लोकल और नेटवर्क के डेटा सोर्स, बुनियादी तौर पर अलग-अलग हो सकते हैं. इससे पता चलता है कि आपका ऐप्लिकेशन पढ़ें और लिखें. लोकल डेटा सोर्स के बारे में क्वेरी तेज़ और सुविधाजनक हो सकती है. जैसे कि एसक्यूएल क्वेरी का इस्तेमाल करते समय. इसके उलट, नेटवर्क डेटा सोर्स धीमे हो सकते हैं और सीमित, जैसे कि आईडी से RESTful संसाधनों को लगातार ऐक्सेस करना. बतौर नतीजे के तौर पर, हर डेटा सोर्स को अक्सर डेटा को खुद दिखाने की ज़रूरत होती है उपलब्ध कराता है. इसलिए, हो सकता है कि लोकल डेटा सोर्स और नेटवर्क डेटा सोर्स में निजी मॉडल का इस्तेमाल करती हैं.

नीचे दी गई डायरेक्ट्री का स्ट्रक्चर, इस कॉन्सेप्ट को दिखाता है. AuthorEntity ऐप्लिकेशन के लोकल डेटाबेस से पढ़े गए लेखक के बारे में जानकारी देनी होगी और NetworkAuthor नेटवर्क पर क्रम से लगाए गए लेखक का प्रतिनिधित्व:

data/
├─ local/
│ ├─ entities/
│ │ ├─ AuthorEntity
│ ├─ dao/
│ ├─ NiADatabase
├─ network/
│ ├─ NiANetwork
│ ├─ models/
│ │ ├─ NetworkAuthor
├─ model/
│ ├─ Author
├─ repository/

AuthorEntity और NetworkAuthor की जानकारी इस तरह से दी गई है:

/**
 * Network representation of [Author]
 */
@Serializable
data class NetworkAuthor(
    val id: String,
    val name: String,
    val imageUrl: String,
    val twitter: String,
    val mediumPage: String,
    val bio: String,
)

/**
 * Defines an author for either an [EpisodeEntity] or [NewsResourceEntity].
 * It has a many-to-many relationship with both entities
 */
@Entity(tableName = "authors")
data class AuthorEntity(
    @PrimaryKey
    val id: String,
    val name: String,
    @ColumnInfo(name = "image_url")
    val imageUrl: String,
    @ColumnInfo(defaultValue = "")
    val twitter: String,
    @ColumnInfo(name = "medium_page", defaultValue = "")
    val mediumPage: String,
    @ColumnInfo(defaultValue = "")
    val bio: String,
)

AuthorEntity और NetworkAuthor, दोनों को बनाए रखना एक अच्छी आदत है डेटा लेयर के लिए इंटरनल इस्तेमाल करता है और बाहरी लेयर के लिए तीसरे टाइप को दिखाता है. इस्तेमाल करते हैं. यह ऐप्लिकेशन लेयर के लोकल स्टोरेज में होने वाले मामूली बदलावों से, बाहरी लेयर को सुरक्षित रखता है नेटवर्क के ऐसे डेटा सोर्स जो ऐप्लिकेशन के काम करने के तरीके में बुनियादी बदलाव नहीं करते. इसे नीचे दिए गए स्निपेट में दिखाया गया है:

/**
 * External data layer representation of a "Now in Android" Author
 */
data class Author(
    val id: String,
    val name: String,
    val imageUrl: String,
    val twitter: String,
    val mediumPage: String,
    val bio: String,
)

इसके बाद, नेटवर्क मॉडल एक एक्सटेंशन का तरीका तय करके, उसे लोकल एक्सटेंशन में बदल सकता है मॉडल है, और स्थानीय मॉडल में भी उसे बाहरी मॉडल के लिए नीचे दिखाई गई जानकारी के मुताबिक करें:

/**
 * Converts the network model to the local model for persisting
 * by the local data source
 */
fun NetworkAuthor.asEntity() = AuthorEntity(
    id = id,
    name = name,
    imageUrl = imageUrl,
    twitter = twitter,
    mediumPage = mediumPage,
    bio = bio,
)

/**
 * Converts the local model to the external model for use
 * by layers external to the data layer
 */
fun AuthorEntity.asExternalModel() = Author(
    id = id,
    name = name,
    imageUrl = imageUrl,
    twitter = twitter,
    mediumPage = mediumPage,
    bio = bio,
)

पढ़ना

रीड, ऑफ़लाइन-पहले ऐप्लिकेशन में मौजूद ऐप्लिकेशन के डेटा की बुनियादी कार्रवाई होती है. आपने लोगों तक पहुंचाया मुफ़्त में इसलिए, यह पक्का करना ज़रूरी है कि आपका ऐप्लिकेशन डेटा को पढ़ सके और जितनी जल्दी हो सके डेटा उपलब्ध हो जिसे ऐप्लिकेशन दिखा सके. ऐसा करने वाला ऐप्लिकेशन रिऐक्टिव है ऐप्लिकेशन में एक्सपोर्ट नहीं किया जा सकता, क्योंकि वे मॉनिटर किए जा सकने वाले टाइप के साथ रीड एपीआई दिखाते हैं.

नीचे दिए गए स्निपेट में, OfflineFirstTopicRepository सभी के लिए Flows लौटाता है इसके रीड एपीआई. इससे अपडेट मिलने पर, Play Store पर लोगों को अपडेट किया जा सकता है नेटवर्क डेटा सोर्स से. अन्य शब्दों में, यह आपको OfflineFirstTopicRepository पुश तब बदलता है, जब इसका लोकल डेटा सोर्स यह होता है अमान्य है. इसलिए, OfflineFirstTopicRepository के हर रीडर को नेटवर्क कनेक्टिविटी के दौरान ट्रिगर होने वाले डेटा में होने वाले बदलावों को हैंडल करने के लिए तैयार रहें ऐप्लिकेशन में वापस लाया जाता है. इसके अलावा, OfflineFirstTopicRepository डेटा को पढ़ता है डेटा सोर्स से ही लिया जा सकता है. यह सिर्फ़ अपने पाठकों को डेटा के बारे में सूचित कर सकता है पहले उसके स्थानीय डेटा सोर्स को अपडेट करके परिवर्तन करता है.

class OfflineFirstTopicsRepository(
    private val topicDao: TopicDao,
    private val network: NiaNetworkDataSource,
) : TopicsRepository {

    override fun getTopicsStream(): Flow<List<Topic>> =
        topicDao.getTopicEntitiesStream()
            .map { it.map(TopicEntity::asExternalModel) }
}

गड़बड़ी ठीक करने की रणनीतियां

ऑफ़लाइन-पहले ऐप्लिकेशन में गड़बड़ियों से निपटने के अलग-अलग तरीके हैं. यह तरीका अलग-अलग है डेटा सोर्स में दिखाए जाते हैं. इन सब-सेक्शन में, रणनीतियां.

स्थानीय डेटा सोर्स

लोकल डेटा सोर्स से पढ़ते समय, कभी-कभी गड़बड़ियां हो सकती हैं. सुरक्षित करने के लिए गड़बड़ियों को ठीक करने के लिए, उस Flows पर catch ऑपरेटर का इस्तेमाल करें जिससे रीडर डेटा इकट्ठा कर रहा है.

ViewModel में catch ऑपरेटर का इस्तेमाल इस तरह से किया जाता है:

class AuthorViewModel(
    authorsRepository: AuthorsRepository,
    ...
) : ViewModel() {
   private val authorId: String = ...

   // Observe author information
    private val authorStream: Flow<Author> =
        authorsRepository.getAuthorStream(
            id = authorId
        )
        .catch { emit(Author.empty()) }
}

नेटवर्क डेटा सोर्स

अगर नेटवर्क डेटा सोर्स से डेटा पढ़ते समय गड़बड़ियां होती हैं, तो ऐप्लिकेशन को का इस्तेमाल करें. सामान्य अनुभवों में ये शामिल हैं:

एक्स्पोनेंशियल बैकऑफ़

एक्सपोनेन्शियल बैकऑफ़ में, ऐप्लिकेशन किसी भी पेज से पढ़ने की कोशिश करता रहता है समय के अंतराल को बढ़ते हुए नेटवर्क डेटा सोर्स के साथ तब तक अपडेट करते हैं, जब तक यह काम नहीं करता या बाकी शर्तें तय करती हैं कि इसे बंद करना चाहिए.

एक्स्पोनेंशियल बैकऑफ़ के साथ डेटा पढ़ना
दूसरी इमेज: एक्स्पोनेंशियल बैकऑफ़ के साथ डेटा पढ़ना

यह मूल्यांकन करने के लिए मानदंड में शामिल है कि ऐप्लिकेशन को बैक अप लेना जारी रखना चाहिए या नहीं:

  • नेटवर्क डेटा सोर्स में जिस तरह की गड़बड़ी बताई गई है. उदाहरण के लिए, आपको उन नेटवर्क कॉल को फिर से आज़माएं जो गड़बड़ी की वजह से, कोई गड़बड़ी दिखाता है कनेक्टिविटी. इसके उलट, आपको उन एचटीटीपी अनुरोधों को फिर से नहीं करना चाहिए जो अनुमति तब तक दी जा सकती है, जब तक कि सही क्रेडेंशियल उपलब्ध नहीं हो जाते.
  • इससे ज़्यादा बार कोशिश करने की अनुमति नहीं है.
नेटवर्क कनेक्टिविटी मॉनिटरिंग

इस तरीके में, मैसेज पढ़ने के अनुरोधों को तब तक सूची में नहीं रखा जाता, जब तक ऐप्लिकेशन यह पक्का नहीं कर लेता कि ये अनुरोध कर सकते हैं नेटवर्क डेटा सोर्स से कनेक्ट करते हैं. संपर्क बन जाने के बाद, इसके बाद, रीड रिक्वेस्ट को हटा दिया जाता है और डेटा को पढ़ लिया जाता है और लोकल डेटा सोर्स अपडेट हो जाता है. Android पर इस सूची को रूम डेटाबेस की मदद से मैनेज किया जा सकता है और इस सूची को इस तरह से खाली किया जा सकता है WorkManager का इस्तेमाल करके लगातार काम करता रहता है.

नेटवर्क मॉनिटर और सूचियों की मदद से डेटा पढ़ा जा रहा है
तीसरी इमेज: नेटवर्क को मॉनिटर करने की सुविधा की मदद से, सूची देखें

लिखना

ऑफ़लाइन-पहले वाले ऐप्लिकेशन में डेटा पढ़ने के लिए सुझाया गया तरीका, मॉनिटर किए जा सकने वाले टाइप के मामले में, राइट एपीआई के तौर पर, एसिंक्रोनस एपीआई का इस्तेमाल सस्पेंड फ़ंक्शन के तौर पर करता है. इससे यूज़र इंटरफ़ेस (यूआई) थ्रेड ब्लॉक नहीं होता और गड़बड़ी ठीक करने में मदद मिलती है हैंडल करना, क्योंकि ऑफ़लाइन मोड में इस्तेमाल होने वाले ऐप्लिकेशन में राइटिंग, नेटवर्क क्रॉस करते समय शायद काम न करे सीमा.

interface UserDataRepository {
    /**
     * Updates the bookmarked status for a news resource
     */
    suspend fun updateNewsResourceBookmark(newsResourceId: String, bookmarked: Boolean)
}

ऊपर दिए गए स्निपेट में, पसंद का एसिंक्रोनस एपीआई Coroutines है निलंबन के बाद का तरीका.

रणनीतियां लिखें

ऑफ़लाइन मोड में इस्तेमाल किए जाने वाले ऐप्लिकेशन में डेटा लिखते समय, तीन रणनीतियों को ध्यान में रखा जा सकता है. आपके चुने गए डेटा का टाइप, इस्तेमाल किए जाने वाले डेटा और ज़रूरी शर्तों के हिसाब से तय होता है ऐप में मौजूद हैं:

सिर्फ़ ऑनलाइन तरीके से लिखा गया कॉन्टेंट

नेटवर्क सीमा के पार डेटा लिखने का प्रयास करें. अगर सफल होता है, तो स्थानीय डेटा स्रोत का इस्तेमाल करें, नहीं तो अपवाद दें और उसे कॉलर के लिए छोड़ दें सही जवाब दें.

सिर्फ़ ऑनलाइन प्लैटफ़ॉर्म पर लिखा गया कॉन्टेंट
चौथी इमेज: सिर्फ़ ऑनलाइन प्लैटफ़ॉर्म पर लिखी गई जानकारी

इस कार्यनीति का उपयोग अक्सर ऐसे व्यक्तिगत लेन-देन लिखने के लिए किया जाता है, जो इतने समय में ऑनलाइन होते हैं करीब-करीब रीयल टाइम में. उदाहरण के लिए, बैंक ट्रांसफ़र. लिखना विफल हो सकता है, इसलिए अक्सर ऐसा होता है उपयोगकर्ता को यह बताना ज़रूरी है कि बदलाव नहीं किया जा सका या उपयोगकर्ता को इस अनुमति से रोका जा सकता है में से कोई भी डेटा लिखने का प्रयास करता है. इन रणनीतियों का इस्तेमाल किया जा सकता है इनमें ये शामिल हो सकते हैं:

  • अगर किसी ऐप्लिकेशन को डेटा लिखने के लिए इंटरनेट ऐक्सेस की ज़रूरत है, तो हो सकता है कि वह स्क्रीन शेयर न करे उपयोगकर्ता के लिए ऐसा यूज़र इंटरफ़ेस (यूआई) जो उपयोगकर्ता को डेटा लिखने की अनुमति देता है या इसे बंद कर देता है.
  • इसके लिए, ऐसे पॉप-अप मैसेज का इस्तेमाल किया जा सकता है जिसे उपयोगकर्ता खारिज नहीं कर सकता. इसके अलावा, कुछ समय के लिए दिखने वाले प्रॉम्प्ट का भी इस्तेमाल किया जा सकता है, का इस्तेमाल करें, ताकि उपयोगकर्ता को बताया जा सके कि वे ऑफ़लाइन हैं.

कतार में लिखे गए लेख

जब आपके पास कोई ऐसा ऑब्जेक्ट होता है जिसे आपको लिखना है, तो उसे सूची में डालें. आगे बढ़ें ऐप्लिकेशन के वापस ऑनलाइन आने पर एक्सपोनेन्शियल बैक ऑफ़ के साथ सूची को तेज़ी से खत्म करने के लिए. चालू है Android के लिए, ऑफ़लाइन सूची को ज़रूरत से ज़्यादा खर्च करना एक स्थायी काम है. इसे अक्सर WorkManager.

सूची बनाने के लिए, फिर से कोशिश करें
पांचवीं इमेज: क्यू की सूची को फिर से कोशिश करना

यह तरीका अच्छा है, अगर:

  • यह ज़रूरी नहीं है कि डेटा कभी भी नेटवर्क पर लिखा जाए.
  • यह लेन-देन, समय के हिसाब से नहीं किया जाता.
  • कार्रवाई विफल होने पर उपयोगकर्ता को सूचित किया जाना ज़रूरी नहीं है.

इसके लिए, आंकड़ों से जुड़े इवेंट और जानकारी को लॉग किया जाता है.

लेज़ी राइट्स

पहले स्थानीय डेटा स्रोत में लिखें, फिर नेटवर्क को सूचित करने के लिए लिखें जल्द से जल्द नहीं करेगा. यह आसान नहीं है, क्योंकि इसमें कई विवाद हो सकते हैं नेटवर्क और स्थानीय डेटा स्रोतों के बीच सेट कर देता है. कॉन्टेंट बनाने समस्या के समाधान के बारे में अगले सेक्शन में ज़्यादा जानकारी दी गई है.

नेटवर्क को मॉनिटर करने की सुविधा के साथ लेज़ी राइटिंग
छठी इमेज: लेज़ी राइट

जब ऐप्लिकेशन के लिए डेटा ज़रूरी हो, तब यह तरीका सही विकल्प होता है. इसके लिए उदाहरण के लिए, पहले ऑफ़लाइन होने पर इस्तेमाल किए जाने वाले कामों की सूची वाले ऐप्लिकेशन में, यह ज़रूरी है कि उपयोगकर्ता ने जो ऑफ़लाइन जोड़ा है उसे डिवाइस पर सेव किया जाता है, ताकि डेटा खोने के जोखिम से बचा जा सके.

सिंक्रोनाइज़ेशन और कॉन्फ़्लिक्ट रिज़ॉल्यूशन

जब कोई ऑफ़लाइन ऐप्लिकेशन अपनी कनेक्टिविटी फिर से चालू करता है, तो उसे अपने लोकल डेटा सोर्स में उस डेटा के साथ जिसे नेटवर्क डेटा सोर्स में भी शामिल किया गया है. यह प्रोसेस को सिंक्रोनाइज़ेशन कहा जाता है. किसी ऐप्लिकेशन को सिंक करने के दो मुख्य तरीके हैं अपने नेटवर्क डेटा सोर्स से:

  • पुल-आधारित सिंक्रोनाइज़ेशन
  • पुश-आधारित सिंक करना

पुल-आधारित सिंक्रोनाइज़ेशन

पुल-आधारित सिंक करने के दौरान, ऐप्लिकेशन मांग पर उपलब्ध ऐप्लिकेशन का नया डेटा उपलब्ध कराया जाता है. इस तरीके का एक सामान्य अनुमान यह है नेविगेशन पर आधारित होता है. इसमें ऐप्लिकेशन, डेटा को प्रज़ेंट करने से ठीक पहले ही उसे फ़ेच करता है उपयोगकर्ता है.

यह तरीका तब सबसे अच्छी तरह काम करता है, जब ऐप्लिकेशन को इंटरनेट कनेक्शन नहीं है. ऐसा इसलिए होता है, क्योंकि डेटा रीफ़्रेश होने की संभावना ज़्यादा होती है. साथ ही, यह लंबे समय तक काम करता है कनेक्टिविटी न होने पर, इस बात की संभावना बढ़ जाती है कि उपयोगकर्ता आपके ऐप्लिकेशन के डेस्टिनेशन पर ऐसे कैश मेमोरी का इस्तेमाल कर सकते हैं जो पुरानी या खाली है.

पुल आधारित सिंक्रोनाइज़ेशन
इमेज 7: पुल पर आधारित सिंक करने की सुविधा: डिवाइस A, स्क्रीन A और B के लिए संसाधनों को ऐक्सेस करता है हालांकि, डिवाइस B सिर्फ़ स्क्रीन B, C, और D के लिए संसाधनों को ऐक्सेस करता है

ऐसा ऐप्लिकेशन इस्तेमाल करें जिसमें पेज टोकन का इस्तेमाल करके, कभी न खत्म होने वाले आइटम फ़ेच किए जाते हों स्क्रोलिंग सूची दिखेगी. लागू करने पर, आसानी से निर्देश दिए जा सकते हैं स्थानीय डेटा स्रोत में डेटा बनाए रखता है और फिर स्थानीय डेटा स्रोत का इस्तेमाल किया है. ऐसे मामले में जहां कोई नेटवर्क कनेक्टिविटी नहीं है, इसलिए डेटा स्टोर करने की जगह, लोकल नेटवर्क से डेटा का अनुरोध कर सकती है डेटा सोर्स का इस्तेमाल करें. यह पैटर्न Jetpack पेजिंग लाइब्रेरी में इस्तेमाल किया जाता है अपने RemoteMediator एपीआई के साथ काम करना.

class FeedRepository(...) {

    fun feedPagingSource(): PagingSource<FeedItem> { ... }
}

class FeedViewModel(
    private val repository: FeedRepository
) : ViewModel() {
    private val pager = Pager(
        config = PagingConfig(
            pageSize = NETWORK_PAGE_SIZE,
            enablePlaceholders = false
        ),
        remoteMediator = FeedRemoteMediator(...),
        pagingSourceFactory = feedRepository::feedPagingSource
    )

    val feedPagingData = pager.flow
}

पुल-आधारित सिंक करने की सुविधा के फ़ायदों और नुकसानों के बारे में यहां बताया गया है नीचे दी गई टेबल:

फ़ायदे नुकसान
इसे लागू करना बाकी होता है. डेटा का बहुत ज़्यादा इस्तेमाल होने की आशंका होती है. ऐसा इसलिए होता है, क्योंकि नेविगेशन डेस्टिनेशन पर बार-बार जाने से, बदली गई जानकारी को फिर से लाना ज़रूरी हो जाता है. सही कैश मेमोरी का इस्तेमाल करके, इस समस्या को कम किया जा सकता है. यह काम cachedIn ऑपरेटर की मदद से यूज़र इंटरफ़ेस (यूआई) लेयर में किया जा सकता है या एचटीटीपी कैश मेमोरी वाली नेटवर्क लेयर में किया जा सकता है.
जिस डेटा की ज़रूरत नहीं है वह कभी भी फ़ेच नहीं किया जाएगा. यह रिलेशनल डेटा के साथ अच्छी तरह से फ़िट नहीं होता, क्योंकि पुल किया गया मॉडल खुद के पूरे होने चाहिए. अगर सिंक किया जा रहा मॉडल, अपने-आप भरे जाने के लिए दूसरे मॉडल को फ़ेच करता है, तो डेटा के इस्तेमाल से जुड़ी जिन समस्याओं के बारे में पहले बताया गया है वे और भी गंभीर हो जाएंगी. साथ ही, ऐसा होने पर, नेस्ट किए गए मॉडल के डेटा स्टोर करने की जगहों और पैरंट मॉडल के डेटा स्टोर करने की जगहों के बीच डिपेंडेंसी हो सकती है.

पुश-आधारित सिंक करना

पुश-आधारित सिंक करने में, लोकल डेटा सोर्स, किसी मॉडल की नकल करने की कोशिश करता है नेटवर्क डेटा स्रोत को अपनी क्षमता के अनुसार बेहतर बनाने का मौका देता है. यह सुविधा लगातार काम करती है बेसलाइन सेट करने के लिए, पहले स्टार्ट-अप पर उचित मात्रा में डेटा फ़ेच करता है, जो डेटा के बारे में सूचना देने के लिए सर्वर से मिली सूचनाओं का इस्तेमाल करता है पुराना.

पुश-आधारित सिंक करना
इमेज 8: पुश पर आधारित सिंक्रोनाइज़ेशन: डेटा बदलने पर नेटवर्क, ऐप्लिकेशन को इसकी सूचना देता है और ऐप्लिकेशन, बदला गया डेटा फ़ेच करके जवाब देता है

पुरानी सूचना मिलने पर, ऐप्लिकेशन इस काम के लिए नेटवर्क से संपर्क करता है: सिर्फ़ उस डेटा को अपडेट करें जिसे पुराना के तौर पर मार्क किया गया था. यह काम Repository, जो नेटवर्क के डेटा सोर्स से संपर्क करता है और डेटा सेव करके रखता है स्थानीय डेटा सोर्स में फ़ेच किया गया. रिपॉज़िटरी अपना डेटा मॉनिटर किए जा सकने वाले टाइप के डेटा का इस्तेमाल किया जाएगा, तो पाठकों को किसी भी बदलाव के बारे में सूचना दी जाएगी.

class UserDataRepository(...) {

    suspend fun synchronize() {
        val userData = networkDataSource.fetchUserData()
        localDataSource.saveUserData(userData)
    }
}

इस तरीके में, ऐप्लिकेशन, नेटवर्क के डेटा सोर्स और अन्य लंबे समय तक इसके बिना काम कर सकता है. यह पढ़ने और लिखने, दोनों की सुविधा देता है ऑफ़लाइन होने पर ऐक्सेस करें, क्योंकि यह माना जाता है कि इसमें नवीनतम जानकारी है स्थानीय तौर पर नेटवर्क डेटा सोर्स से.

पुश-आधारित सिंक करने के फ़ायदों और नुकसानों के बारे में यहां खास जानकारी दी गई है नीचे दी गई टेबल:

फ़ायदे नुकसान
ऐप्लिकेशन हमेशा के लिए ऑफ़लाइन रह सकता है. विरोधाभास समाधान के लिए वर्शन डेटा मामूली नहीं होता है.
डेटा का कम से कम इस्तेमाल. ऐप्लिकेशन सिर्फ़ ऐसा डेटा फ़ेच करता है जिसमें बदलाव हुआ है. सिंक करने के दौरान, आपको लिखने से जुड़ी समस्याओं पर ध्यान देना चाहिए.
रिलेशनल डेटा के साथ सही तरीके से काम करता है. हर डेटा स्टोर करने की जगह, सिर्फ़ उस मॉडल से डेटा फ़ेच करने के लिए ज़िम्मेदार होती है जो इसके साथ काम करता है. नेटवर्क के डेटा सोर्स को सिंक करने की सुविधा चाहिए.

हाइब्रिड सिंक करना

कुछ ऐप्लिकेशन, हाइब्रिड तरीके का इस्तेमाल करते हैं. इसमें, डेटा शामिल है. उदाहरण के लिए, कोई सोशल मीडिया ऐप्लिकेशन नीचे दिए गए काम करने के लिए पुल-आधारित सिंक्रोनाइज़ेशन का इस्तेमाल कर सकता है फ़ीड की फ़्रीक्वेंसी ज़्यादा होने की वजह से, उपयोगकर्ता के इस फ़ीड को मांग पर फ़ेच करें अपडेट. वही ऐप्लिकेशन, पुश-आधारित सिंक की सुविधा का इस्तेमाल, साइन इन किए हुए उपयोगकर्ता का नाम, उसका उपयोगकर्ता नाम, प्रोफ़ाइल फ़ोटो वगैरह शामिल होनी चाहिए.

इसलिए, ऑफ़लाइन सिंक करने का विकल्प, प्रॉडक्ट की ज़रूरी शर्तों पर निर्भर करता है और उपलब्ध तकनीकी इंफ़्रास्ट्रक्चर.

विरोध का हल

अगर ऐप्लिकेशन ऑफ़लाइन होने पर स्थानीय रूप से डेटा लिखता है और वह नेटवर्क के साथ अलाइन नहीं है डेटा सोर्स में कोई ऐसी गड़बड़ी हुई है जिसे पहले हल करना ज़रूरी है सिंक हो सकते हैं.

समस्या को हल करने के लिए अक्सर अलग-अलग वर्शन बनाने की ज़रूरत होती है. ऐप्लिकेशन को कुछ काम करने होंगे हिसाब-किताब रखना. इससे यह नेटवर्क डेटा सोर्स का मेटाडेटा. इसके बाद, नेटवर्क डेटा सोर्स में प्रामाणिकता का पूरा सोर्स उपलब्ध कराने की ज़िम्मेदारी है. कई तरह के उपलब्ध हैं समस्याओं को सुलझाने के लिए रणनीतियों का, का इस्तेमाल करें. मोबाइल ऐप्लिकेशन के लिए एक सामान्य तरीका है "पिछली बार लिखा जाना".

पिछली बार कब लिखा गया

इस तरीके से, डिवाइस उस डेटा में टाइमस्टैंप मेटाडेटा जोड़ते हैं जिस पर वे लिखते हैं नेटवर्क. जब नेटवर्क डेटा सोर्स को ये रिपोर्ट मिलती हैं, तो वह किसी भी डेटा को खारिज कर देता है अपनी मौजूदा स्थिति से पुराने होने के साथ-साथ नए बदलावों को स्वीकार करना.

आखिरी बार लिखने के बाद, विवाद सुलझाने की प्रक्रिया में जीत
नौवीं इमेज: "पिछली बार लिखी गई जीत" आखिरी इकाई, डेटा को किस स्रोत से तय करती है डेटा लिखने के लिए

ऊपर बताया गया है कि दोनों डिवाइस ऑफ़लाइन हैं और शुरुआत में नेटवर्क डेटा सोर्स. ऑफ़लाइन रहते हुए, वे दोनों स्थानीय तौर पर डेटा लिखते हैं और ट्रैक करते हैं कितने समय पहले तक उसका डेटा लिखा था. जब वे दोनों ऑनलाइन वापस आते हैं और नेटवर्क डेटा सोर्स के साथ सिंक करते हैं, तो नेटवर्क इस तरह विवाद को हल करता है डिवाइस B का डेटा सेव रहेगा, क्योंकि इसका डेटा बाद में लिखा गया था.

ऑफ़लाइन ऐप्लिकेशन के लिए WorkManager

ऊपर बताई गई रीड और राइटिंग, दोनों रणनीतियों में दो आम बातें थीं सुविधाएं:

  • क्यू की लिस्ट
    • पढ़ना: नेटवर्क कनेक्टिविटी उपलब्ध होने तक पढ़ने के लिए टालने के लिए इस्तेमाल किया जाता है.
    • लिखता है: नेटवर्क कनेक्टिविटी के होने तक लिखने रोकने के लिए इस्तेमाल किया जाता है उपलब्ध है. साथ ही, बार-बार कोशिश करने के लिए लिखा जा सकता है.
  • नेटवर्क कनेक्टिविटी मॉनिटर
    • पढ़ना: जब ऐप्लिकेशन कनेक्ट है और सिंक करने के लिए
    • लिखता है: जब ऐप्लिकेशन कनेक्ट है और सिंक करने के लिए

दोनों केस, WorkManager के लगातार काम के उदाहरण हैं बेहतरीन है. उदाहरण के लिए, Now Android में Now सैंपल ऐप्लिकेशन में, सिंक्रोनाइज़ करते समय WorkManager का इस्तेमाल रीड क्यू और नेटवर्क मॉनिटर, दोनों के तौर पर किया जाता है लोकल डेटा सोर्स को खोज सकें. चालू होने पर, ऐप्लिकेशन ये काम करता है:

  1. यह पक्का करने के लिए पंक्ति में सिंक करने की सुविधा काम करती है कि स्थानीय डेटा सोर्स और नेटवर्क डेटा सोर्स का इस्तेमाल किया जा सकता है.
  2. पढ़ी गई समन्वयन सूची को खत्म करें और जब ऐप्लिकेशन ऑनलाइन.
  3. एक्स्पोनेंशियल बैकऑफ़ का इस्तेमाल करके, नेटवर्क डेटा सोर्स से कोई रीड करें.
  4. किसी भी समस्या का समाधान करने के लिए स्थानीय डेटा सोर्स में रीड के नतीजों को लागू रखना हो सकता है.
  5. ऐप्लिकेशन की अन्य लेयर के लिए, स्थानीय डेटा सोर्स से मिलने वाले डेटा को सार्वजनिक करें इस्तेमाल करते हैं.

ऊपर दिए गए डायग्राम में इसे दिखाया गया है:

Android में Now ऐप्लिकेशन में डेटा सिंक करना
इमेज 10: Now में Android ऐप्लिकेशन में डेटा सिंक करना

सिंक करने की सुविधा की लाइन में, WorkManager को इसे KEEP ExistingWorkPolicy के साथ यूनीक काम के तौर पर बताकर:

class SyncInitializer : Initializer<Sync> {
   override fun create(context: Context): Sync {
       WorkManager.getInstance(context).apply {
           // Queue sync on app startup and ensure only one
           // sync worker runs at any time
           enqueueUniqueWork(
               SyncWorkName,
               ExistingWorkPolicy.KEEP,
               SyncWorker.startUpSyncWork()
           )
       }
       return Sync
   }
}

जहां SyncWorker.startupSyncWork() को नीचे बताए गए तरीके से परिभाषित किया गया है:


/**
 Create a WorkRequest to call the SyncWorker using a DelegatingWorker.
 This allows for dependency injection into the SyncWorker in a different
 module than the app module without having to create a custom WorkManager
 configuration.
*/
fun startUpSyncWork() = OneTimeWorkRequestBuilder<DelegatingWorker>()
    // Run sync as expedited work if the app is able to.
    // If not, it runs as regular work.
   .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
   .setConstraints(SyncConstraints)
    // Delegate to the SyncWorker.
   .setInputData(SyncWorker::class.delegatedData())
   .build()

val SyncConstraints
   get() = Constraints.Builder()
       .setRequiredNetworkType(NetworkType.CONNECTED)
       .build()

खास तौर पर, SyncConstraints के ज़रिए तय किए गए Constraints के लिए यह ज़रूरी है कि NetworkType NetworkType.CONNECTED. इसका मतलब है कि यह तब तक नेटवर्क चालू होने से पहले उपलब्ध रहता है.

नेटवर्क मिल जाने पर, वर्कर काम की खास सूची से बहुत सारे काम हटा देता है SyncWorkName के ज़रिए उचित Repository को सौंपकर तय किया गया है इंस्टेंस. अगर सिंक नहीं हो पाता है, तो doWork() तरीका Result.retry(). WorkManager अपने-आप, इसके साथ सिंक करने की फिर से कोशिश करेगा एक्स्पोनेंशियल बैकऑफ़. ऐसा न करने पर, यह जवाब के तौर पर Result.success() को पूरा करता है सिंक करना.

class SyncWorker(...) : CoroutineWorker(appContext, workerParams), Synchronizer {

    override suspend fun doWork(): Result = withContext(ioDispatcher) {
        // First sync the repositories in parallel
        val syncedSuccessfully = awaitAll(
            async { topicRepository.sync() },
            async { authorsRepository.sync() },
            async { newsRepository.sync() },
        ).all { it }

        if (syncedSuccessfully) Result.success()
        else Result.retry()
    }
}

सैंपल

Google के इन सैंपल में, ऑफ़लाइन ऐप्लिकेशन के बारे में जानकारी दी गई है. इस दिशा-निर्देश को देखने के लिए, उन्हें एक्सप्लोर करें: