मेरे पास एक ऐसा ऐप है जिसे सर्वर से डेटा खींचने और उपयोगकर्ता इनपुट के जवाब में SQLite डेटाबेस में डालने की आवश्यकता होती है। मैंने सोचा कि यह बहुत आसान होगा - सर्वर से डेटा खींचने वाला कोड AsyncTask का एक काफी सरल सबक्लास है, और यह ठीक उसी तरह काम करता है जैसा कि मैं यूआई थ्रेड को लटकाने के बिना उम्मीद करता हूं। मैं एक सरल अंतरफलक के साथ इसके लिए कॉलबैक कार्यक्षमता लागू और एक स्थिर वर्ग में लपेटा, तो मेरे कोड इस तरह दिखता है:ContentProvider insert() हमेशा यूआई थ्रेड पर चलता है?
MyServerCaller.getFolderContents(folderId, new OnFolderContentsResponseListener() {
@Override
public void onFolderContentsResponse(final List<FilesystemEntry> contents) {
// do something with contents
}
}
सभी अभी भी अच्छा है। यहां तक कि यदि सर्वर को डेटा पुनर्प्राप्त करने में एक घंटा लगते हैं, तो यूआई अभी भी सुचारू रूप से चलता है, क्योंकि कोड में फोल्डरकंट्स एक AsyncTask (जो यूआई से अलग थ्रेड में है) की doInBackground विधि में चल रहा है। GetFolderContents विधि के बहुत अंत में, ऑनफोल्डरकंट्स रेस्पॉन्स को सर्वर से प्राप्त फाइल सिस्टम एंट्री की सूची कहा जाता है और पास किया जाता है। मैं केवल इतना ही कहता हूं कि यह उम्मीद है कि मेरी समस्या getFolderContents विधि या मेरे किसी भी नेटवर्किंग कोड में नहीं है, क्योंकि यह कभी नहीं होती है।
समस्या तब उत्पन्न होती है जब मैं ContentProviderResponse विधि के भीतर ContentProvider के अपने उप-वर्ग के माध्यम से डेटाबेस में डालने का प्रयास करता हूं; UI हमेशा उस कोड को निष्पादित करते समय लटकता है, जिससे मुझे विश्वास होता है कि AsyncTask की doInBackground विधि से बुलाए जाने के बावजूद, इन्सर्ट अभी भी यूआई थ्रेड पर चल रहे हैं।
MyServerCaller.getFolderContents(folderId, new OnFolderContentsResponseListener() {
@Override
public void onFolderContentsResponse(final List<FilesystemEntry> contents) {
insertContentsIntoDB(contents);
}
}
और insertContentsIntoDB
विधि:: यहाँ समस्याग्रस्त कोड कैसा दिखता है
void insertContentsIntoDB(final List<FilesystemEntry> contents) {
for (FilesystemEntry entry : contents) {
ContentValues values = new ContentValues();
values.put(COLUMN_1, entry.attr1);
values.put(COLUMN_2, entry.attr2);
// etc.
mContentResolver.insert(MyContentProvider.CONTENT_URI, values);
}
}
जहां mContentResolver पहले विधि getContentResolver() के परिणाम पर सेट किया गया है।
मैं अपनी ही थ्रेड में insertContentsIntoDB डाल, तो तरह की कोशिश की है:
MyServerCaller.getFolderContents(folderId, new OnFolderContentsResponseListener() {
@Override
public void onFolderContentsResponse(final List<FilesystemEntry> contents) {
new Thread(new Runnable() {
@Override
public void run() {
insertContentsIntoDB(contents);
}
}).run();
}
}
मैं भी अपने स्वयं के सूत्र में प्रत्येक व्यक्ति डालने चल कोशिश की है (MyContentProvider में डालने विधि सिंक्रनाइज़ है, तो यह shouldn
void insertContentsIntoDB(final List<FilesystemEntry> contents) {
for (FilesystemEntry entry : contents) {
new Thread(new Runnable() {
@Override
public void run() {
ContentValues values = new ContentValues();
values.put(COLUMN_1, entry.attr1);
values.put(COLUMN_2, entry.attr2);
// etc.
mContentResolver.insert(MyContentProvider.CONTENT_URI, values);
}
}).run();
}
}
और बस अच्छा उपाय, मैं भी उन समाधानों के दोनों एक और AsyncTask की doInBackground विधि में प्रासंगिक कोड के साथ की कोशिश की है: 'टी वहाँ किसी भी मुद्दे) होता है। अंत में, मैं स्पष्ट रूप से मेरे AndroidManifest.xml में एक अलग प्रक्रिया में रहने वाले के रूप में परिभाषित किया है MyContentProvider:
<provider android:name=".MyContentProvider" android:process=":remote"/>
यह ठीक चलाता है, लेकिन यह अभी भी यूआई धागा में चलाने के लिए लगता है। यही वह बिंदु है जहां मैंने वास्तव में इस पर अपने बालों को फाड़ना शुरू कर दिया, क्योंकि इससे मुझे कोई समझ नहीं आती है। कोई फर्क नहीं पड़ता कि मैं क्या करता हूं, यूआई हमेशा आवेषण के दौरान लटकता है। क्या उन्हें पाने के लिए कोई रास्ता नहीं है?
अपनी परिकल्पना को सत्यापित करने के लिए अपने ContentProvider से वर्तमान थ्रेड आईडी/नाम प्रिंट करें। और/या डीबगर का उपयोग करें और चल रहे धागे की जांच करें। –