16

के बीच साझा कोड का उपयोग करते समय वास्तविक 'थ्रेड थ्रेड से एक्सेस' का उपयोग करें मेरे पास कुछ कोड है जो "वर्तमान" ऑब्जेक्ट के JSON को डाउनलोड करता है। लेकिन जब भी अलार्म बंद हो जाता है (जब ऐप कोई यूआई नहीं चला रहा है), और एपिनकटास्क द्वारा ऐप चल रहा है, तो उसी कोड को एक इंटेंट सेवा द्वारा बुलाया जाना चाहिए।IntentService और AsyncTask (एंड्रॉइड)

हालांकि, मुझे Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created. कहने में त्रुटि मिली, हालांकि, मुझे नहीं पता कि यह स्टैक ट्रेस एक अलग थ्रेड पर कैसे या क्यों मिला।

मैं सभी साझा कोड की प्रतिलिपि बनाकर और सीधे इसेDDalService की onHandleIntent विधि में चिपकाकर त्रुटि से छुटकारा पाने में सक्षम था, लेकिन यह बहुत ही गड़बड़ है और मैं एक बेहतर समाधान की तलाश में हूं जिसके लिए डुप्लिकेटिंग कोड की आवश्यकता नहीं है।

कोड को डुप्लिकेट किए बिना, मैं इस त्रुटि से कैसे छुटकारा पा सकता हूं? धन्यवाद।

public class DownloadDealService extends IntentService 
{ 
    ... 
    @Override 
    protected void onHandleIntent(Intent intent) 
    { 
     Current todaysCurrent = Utils.downloadTodaysCurrent(); //<--- included for background info 
     String dateString = Utils.getMehHeadquartersDate(); //(omitted) 
     Utils.onDownloadCurrentCompleteWithAlarm(todaysCurrent, dateString); //<------ calling this... 
    } 
} 

public class Utils 
{ 
    // ...other methods ommitted... 

    //This method is not in the stack trace, but I included it for background information. 
    public static Current downloadTodaysCurrent() 
    { 
     //Set up Gson object... (omitted) 
     //Set up RestAdapter object... (omitted) 
     //Set up MehService class... (omitted) 

     //Download "Current" object from the internet. 
     Current current = mehService.current(MehService.API_KEY); 
     return current; 
    } 

    //Included for background info- this method is not in the stack trace. 
    public static void onDownloadCurrentComplete(Current result, String dateString) 
    { 
     if(result.getVideo() == null) 
     { 
      Log.e("HomePage", "Current was not added on TaskComplete"); 
      return; 
     } 
     remainder(result, dateString); 
    } 

    public static void onDownloadCurrentCompleteWithAlarm(Current result, String dateString) 
    { 
     //Set alarm if download failed and exit this function... (omitted) 

     remainder(result, dateString);//<------ calling this... 
     Utils.sendMehNewDealNotification(App.getContext()); 
    } 

    public static void remainder(Current result, String dateString) 
    { 
     Realm realm = RealmDatabase.getInstance(); 

     //Add "Current" to Realm 
     Current current = Utils.addCurrentToRealm(result, realm); //<------ calling this... 
    } 

    public static Current addCurrentToRealm(Current current, Realm realm) 
    { 
     realm.beginTransaction(); //<---- Error is here 
     Current result = realm.copyToRealmOrUpdate(current); 
     realm.commitTransaction(); 
     return result; 
    } 
} 

स्टैक ट्रेस: ​​

E/AndroidRuntime: FATAL EXCEPTION: IntentService[DownloadDealService] 
Process: com.example.lexi.meh, PID: 13738 
java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created. 
    at io.realm.Realm.checkIfValid(Realm.java:191) 
    at io.realm.Realm.beginTransaction(Realm.java:1449) 
    at com.example.lexi.meh.Utils.Utils.addCurrentToRealm(Utils.java:324) 
    at com.example.lexi.meh.Utils.Utils.remainder(Utils.java:644) 
    at com.example.lexi.meh.Utils.Utils.onDownloadCurrentCompleteWithAlarm(Utils.java:635) 
    at com.example.lexi.meh.Home.DownloadDealService.onHandleIntent(DownloadDealService.java:42) 
    at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:136) 
    at android.os.HandlerThread.run(HandlerThread.java:61) 

मैं एक AsyncTask कि उन Utils भी तरीकों के कुछ कहता है:

public class DownloadAsyncTask extends AsyncTask<Void, Integer, Current> 
{ 
    // ... (more methods ommitted)... 

    protected Current doInBackground(Void... voids) 
    { 
     return Utils.downloadTodaysCurrent(); //<---- shared Utils method 
    } 
} 

//Async class's callback in main activity: 
public class HomePage extends AppCompatActivity implements DownloadAsyncTaskCallback, DownloadAsyncTaskGistCallback<Current, String> 
{ 
    // ... (more methods ommitted)... 

    public void onTaskComplete(Current result, String dateString) 
    { 
     Utils.onDownloadCurrentComplete(result, dateString); 
    } 
} 

उत्तर

18

[अपडेट] अतिरिक्त जानकारी

RealmDatabase.getInstance() मुख्य थ्रेड पर बनाया क्षेत्र उदाहरण लौट रहा था पर आधारित है। और इस उदाहरण का उपयोग IntentService के धागे पर किया गया था। जो दुर्घटना का कारण बनता है।

वास्तविक उदाहरणों को किसी भी अन्य धागे पर इस्तेमाल नहीं किया जा सकता है, जिसे वे बनाए गए थे।


आप धागे के बीच दायरे की वस्तुओं को पार नहीं कर सकते हैं। आप ऑब्जेक्ट का एक अद्वितीय पहचानकर्ता (यानी @PrimaryKey) पास करने के लिए क्या कर सकते हैं, और फिर ऑब्जेक्ट को अपने आईडी द्वारा किसी अन्य थ्रेड पर लाएं। इस तरह: realm.where (YourRealmModel.class) .equalTo ("PrimaryKeyVariable", id) .findFirst()।

अधिक जानकारी के लिए बाहर की जाँच क्षेत्र के आधिकारिक दस्तावेज और उदाहरण:

+0

क्या आप मेरे कोड को देख सकते हैं और मुझे बता सकते हैं कि मैंने धागे के बीच कुछ भी पारित किया था? मुझे समझ में नहीं आता मैंने ईमानदारी से सोचा कि मैं एक ही थ्रेड पर था। जहां तक ​​मुझे पता है, मैंने केवल थ्रेड के बीच विधियों को साझा किया है, धागे के बीच किसी भी वास्तविक वस्तु को पास नहीं किया है। –

+0

यह समझना बहुत मुश्किल है कि आपके कोड उदाहरण से कहां जाता है।लेकिन मुझे लगता है कि आप AsyncTask (जिसे वर्कर थ्रेड पर निष्पादित किया गया है) के doInBackround में परिणाम ऑब्जेक्ट प्राप्त होता है और उसके बाद इसे PostExecute() (जिसे मुख्य थ्रेड पर निष्पादित किया जाता है) के परिणामस्वरूप पास किया जाता है। और उसके बाद शेष() विधि पर वहां से पहुंचने का प्रयास कर रहा है, जो आपके ऐप को उड़ाता है। –

+0

आप निष्पादन के पथ को देखने के लिए प्रदान किए गए स्टैक ट्रेस में देख सकते हैं। IntentService 'DownloadDealService' मेरी' Util.java' कक्षा में कुछ स्थिर तरीकों को कॉल करता है। –

0

समस्या आप विभिन्न धागे से तरीकों बुला रहे हैं है, आपके पास एक ही धागे का उपयोग करने के लिए, अपना खुद का हैंडलर थ्रेड बनाएं।

0

आप IntentService में क्षेत्र का उपयोग करते हैं भर में एक क्षेत्र का उपयोग करना, आप का उपयोग करेगा नया दायरा। उदाहरण के लिए

Realm.getInstance(RealmConfiguration config) 

मैंने प्रैक्टम इन इंटेंट सर्विस

@Override 
protected void onHandleIntent(Intent intent) { 
    Realm realm = Realm.getDefaultInstance(); 
    ... 
    realm.close(); // important on background thread 
} 
संबंधित मुद्दे