2016-11-24 12 views
17

के बीच अंतर मुझे यह समझने के लिए दिया गया है कि दोनों एक जैसे हैं। लेकिन मैंने हाल ही में (पार्टी के लिए थोड़ा देर हो चुकी है) android support annotations पर आई। एक ही में नोट हैमुख्य धागे और यूआई थ्रेड

हालांकि, यह संभव है के लिए एक यूआई धागा अलग धागे पर अनेक दृश्य के साथ प्रणाली ऐप्लिकेशन के मामले में मुख्य धागे से अलग होने की

मैं यहां दृश्य को समझने में असमर्थ। क्या कोई इसे समझा सकता है?

संपादित करें: मैं डेवलपर दस्तावेज़ीकरण से गुजर चुका हूं और यह इस प्रश्न में जुड़े समर्थन दस्तावेज़ का विरोधाभास कर रहा है। कृपया दोनों पोस्ट करना बंद करें वही हैं।

+0

को क्रेडिट कृपया इस लिंक http://stackoverflow.com/questions/3261370/is-main-thread-the-same-as-ui-thread – Swapnil

+3

कि does not मेरे सवाल और जवाब के माध्यम से जाना विशेष रूप से – humblerookie

उत्तर

32

असाधारण रूप से दिलचस्प प्रश्न के लिए धन्यवाद।

बाहर निकलता है, यूआई और मुख्य धागे जरूरी नहीं हैं। हालांकि, जैसा कि आपने उद्धृत दस्तावेज में बताया है, भेद केवल कुछ सिस्टम अनुप्रयोगों (ओएस के हिस्से के रूप में चलाने वाले अनुप्रयोगों) के संदर्भ में महत्वपूर्ण है। इसलिए, जब तक आप कस्टम निर्माताओं का निर्माण नहीं करते हैं या फोन निर्माताओं के लिए एंड्रॉइड को अनुकूलित करने पर काम करते हैं, तो मैं किसी भी भेद को परेशान नहीं करता।

विस्तृत उत्तर:

commit 774c065affaddf66d4bec1126183435f7c663ab0 
Author: Tor Norbye <[email protected]> 
Date: Tue Mar 10 19:12:04 2015 -0700 

    Add threading annotations 

    These describe threading requirements for a given method, 
    or threading promises made to a callback. 

    Change-Id: I802d2415c5fa60bc687419bc2564762376a5b3ef 

टिप्पणी प्रश्न से संबंधित कोई जानकारी नहीं होती है:

सबसे पहले मैं प्रतिबद्ध है कि समर्थन पुस्तकालय में @MainThread और @UiThread एनोटेशन पेश किया पाया , और चूंकि मेरे पास टोर नोर्बी (श्वास) के लिए एक संचार चैनल नहीं है, यहां कोई भाग्य नहीं है।

शायद इन एनोटेशन का उपयोग एओएसपी के स्रोत कोड में किया जा रहा है और हम वहां से कुछ अंतर्दृष्टि प्राप्त कर सकते हैं? के AOSP में एनोटेशन में से किसी के उपयोगों के लिए खोज करते हैं:

aosp $ find ./ -name *.java | xargs perl -nle 'print "in file: ".$ARGV."; match: ".$& if m{(\@MainThread|\@UiThread)(?!Test).*}' 
aosp $ 

उपरोक्त आदेश AOSP में किसी भी जावा फाइल (नहीं अतिरिक्त Test स्ट्रिंग हो) में @MainThread या @UiThread के किसी भी उपयोग पाते हैं। यह कुछ भी नहीं मिला। यहां कोई भाग्य नहीं है।

इसलिए हमें एओएसपी के स्रोत में संकेतों की तलाश करने और संकेतों की तलाश करने की आवश्यकता है। मैं अनुमान लगाया है कि मैं Activity#runOnUiThread(Runnable) विधि से शुरू कर सकता है: विशेष रूप से यहां दिलचस्प

public final void runOnUiThread(Runnable action) { 
    if (Thread.currentThread() != mUiThread) { 
     mHandler.post(action); 
    } else { 
     action.run(); 
    } 
} 

कुछ भी नहीं। चलो देखते हैं कैसे mUiThread सदस्य प्रारंभ किया जा रहा है:

final void attach(Context context, ActivityThread aThread, 
     Instrumentation instr, IBinder token, int ident, 
     Application application, Intent intent, ActivityInfo info, 
     CharSequence title, Activity parent, String id, 
     NonConfigurationInstances lastNonConfigurationInstances, 
     Configuration config, String referrer, IVoiceInteractor voiceInteractor) { 
    attachBaseContext(context); 

    mFragments.attachActivity(this, mContainer, null); 

    mWindow = PolicyManager.makeNewWindow(this); 
    mWindow.setCallback(this); 
    mWindow.setOnWindowDismissedCallback(this); 
    mWindow.getLayoutInflater().setPrivateFactory(this); 
    if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { 
     mWindow.setSoftInputMode(info.softInputMode); 
    } 
    if (info.uiOptions != 0) { 
     mWindow.setUiOptions(info.uiOptions); 
    } 
    mUiThread = Thread.currentThread(); 

    mMainThread = aThread; 

    // ... more stuff here ... 
} 

जैकपॉट! आखिरी दो पंक्तियां (अन्य छोड़े गए क्योंकि वे अप्रासंगिक हैं) वे पहले संकेत हैं कि "मुख्य" और "ui" धागे वास्तव में अलग-अलग धागे हो सकते हैं।

"ui" धागा की धारणा इस पंक्ति से स्पष्ट है mUiThread = Thread.currentThread(); - "ui" धागा वह धागा है जिस पर Activity#attach(<params>) विधि कहा जा रहा है। इसलिए हमें यह पता लगाना होगा कि "मुख्य" धागा क्या है और दोनों की तुलना करें।

ऐसा लगता है कि अगला संकेत ActivityThread कक्षा में पाया जा सकता है। यह वर्ग काफी स्पेगेटी है, लेकिन मुझे लगता है कि दिलचस्प भाग हैं जहां ActivityThread वस्तुओं को तत्काल किया जा रहा है।

केवल दो स्थान हैं: public static void main(String[]) और public static ActivityThread systemMain()

इन तरीकों में से स्रोत:

public static void main(String[] args) { 
    SamplingProfilerIntegration.start(); 

    // CloseGuard defaults to true and can be quite spammy. We 
    // disable it here, but selectively enable it later (via 
    // StrictMode) on debug builds, but using DropBox, not logs. 
    CloseGuard.setEnabled(false); 

    Environment.initForCurrentUser(); 

    // Set the reporter for event logging in libcore 
    EventLogger.setReporter(new EventLoggingReporter()); 

    Security.addProvider(new AndroidKeyStoreProvider()); 

    // Make sure TrustedCertificateStore looks in the right place for CA certificates 
    final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); 
    TrustedCertificateStore.setDefaultUserDirectory(configDir); 

    Process.setArgV0("<pre-initialized>"); 

    Looper.prepareMainLooper(); 

    ActivityThread thread = new ActivityThread(); 
    thread.attach(false); 

    if (sMainThreadHandler == null) { 
     sMainThreadHandler = thread.getHandler(); 
    } 

    if (false) { 
     Looper.myLooper().setMessageLogging(new 
       LogPrinter(Log.DEBUG, "ActivityThread")); 
    } 

    Looper.loop(); 

    throw new RuntimeException("Main thread loop unexpectedly exited"); 
} 

और:

public static ActivityThread systemMain() { 
    // The system process on low-memory devices do not get to use hardware 
    // accelerated drawing, since this can add too much overhead to the 
    // process. 
    if (!ActivityManager.isHighEndGfx()) { 
     HardwareRenderer.disable(true); 
    } else { 
     HardwareRenderer.enableForegroundTrimming(); 
    } 
    ActivityThread thread = new ActivityThread(); 
    thread.attach(true); 
    return thread; 
} 

नोट भिन्न मान इन तरीकों attach(boolean) लिए गुजरती हैं। पूर्णता के लिए मैं अपने स्रोत पोस्ट करेंगे और साथ ही:

private void attach(boolean system) { 
    sCurrentActivityThread = this; 
    mSystemThread = system; 
    if (!system) { 
     ViewRootImpl.addFirstDrawHandler(new Runnable() { 
      @Override 
      public void run() { 
       ensureJitEnabled(); 
      } 
     }); 
     android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", 
               UserHandle.myUserId()); 
     RuntimeInit.setApplicationObject(mAppThread.asBinder()); 
     final IActivityManager mgr = ActivityManagerNative.getDefault(); 
     try { 
      mgr.attachApplication(mAppThread); 
     } catch (RemoteException ex) { 
      // Ignore 
     } 
     // Watch for getting close to heap limit. 
     BinderInternal.addGcWatcher(new Runnable() { 
      @Override public void run() { 
       if (!mSomeActivitiesChanged) { 
        return; 
       } 
       Runtime runtime = Runtime.getRuntime(); 
       long dalvikMax = runtime.maxMemory(); 
       long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); 
       if (dalvikUsed > ((3*dalvikMax)/4)) { 
        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) 
          + " total=" + (runtime.totalMemory()/1024) 
          + " used=" + (dalvikUsed/1024)); 
        mSomeActivitiesChanged = false; 
        try { 
         mgr.releaseSomeActivities(mAppThread); 
        } catch (RemoteException e) { 
        } 
       } 
      } 
     }); 
    } else { 
     // Don't set application object here -- if the system crashes, 
     // we can't display an alert, we just want to die die die. 
     android.ddm.DdmHandleAppName.setAppName("system_process", 
       UserHandle.myUserId()); 
     try { 
      mInstrumentation = new Instrumentation(); 
      ContextImpl context = ContextImpl.createAppContext(
        this, getSystemContext().mPackageInfo); 
      mInitialApplication = context.mPackageInfo.makeApplication(true, null); 
      mInitialApplication.onCreate(); 
     } catch (Exception e) { 
      throw new RuntimeException(
        "Unable to instantiate Application():" + e.toString(), e); 
     } 
    } 

    // add dropbox logging to libcore 
    DropBox.setReporter(new DropBoxReporter()); 

    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() { 
     @Override 
     public void onConfigurationChanged(Configuration newConfig) { 
      synchronized (mResourcesManager) { 
       // We need to apply this change to the resources 
       // immediately, because upon returning the view 
       // hierarchy will be informed about it. 
       if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) { 
        // This actually changed the resources! Tell 
        // everyone about it. 
        if (mPendingConfiguration == null || 
          mPendingConfiguration.isOtherSeqNewer(newConfig)) { 
         mPendingConfiguration = newConfig; 

         sendMessage(H.CONFIGURATION_CHANGED, newConfig); 
        } 
       } 
      } 
     } 
     @Override 
     public void onLowMemory() { 
     } 
     @Override 
     public void onTrimMemory(int level) { 
     } 
    }); 
} 

क्यों ActivityThread आरंभ के लिए दो साधन हैं (जो आवेदन की "मुख्य" धागा हो जाएगा)?

जब भी कोई नया आवेदन शुरू कर दिया, ActivityThread की public static void main(Strin[]) विधि निष्पादित किया जा रहा है:

मैं निम्नलिखित लगता है जगह लेता है। "मुख्य" थ्रेड को प्रारंभ किया जा रहा है, और Activity लाइफसाइकिल विधियों के सभी कॉल उस सटीक धागे से बनाए जा रहे हैं। Activity#attach() विधि (इसका स्रोत ऊपर दिखाया गया था) में सिस्टम "ui" थ्रेड को "इस" थ्रेड में प्रारंभ करता है, जो "मुख्य" थ्रेड भी होता है। इसलिए, सभी व्यावहारिक मामलों के लिए "मुख्य" धागा और "ui" धागा समान हैं।

यह एक अपवाद के साथ सभी अनुप्रयोगों के लिए सच है।

जब पहली बार एंड्रॉइड फ्रेमवर्क शुरू किया जा रहा है, तो यह भी एक एप्लिकेशन के रूप में चलता है, लेकिन यह एप्लिकेशन विशेष है (उदाहरण के लिए: विशेषाधिकार प्राप्त पहुंच है)। इस "विशेषता" का हिस्सा यह है कि इसे विशेष रूप से कॉन्फ़िगर किए गए "मुख्य" थ्रेड की आवश्यकता होती है। चूंकि यह पहले से ही public static void main(String[]) विधि (किसी भी अन्य ऐप की तरह) से गुजर चुका है, इसके "मुख्य" और "ui" थ्रेड एक ही थ्रेड पर सेट किए जा रहे हैं। विशेष विशेषताओं के साथ "मुख्य" थ्रेड प्राप्त करने के लिए, सिस्टम ऐप public static ActivityThread systemMain() पर एक स्थिर कॉल करता है और प्राप्त संदर्भ संग्रहीत करता है। लेकिन इसका "यूई" थ्रेड ओवरराइड नहीं है, इसलिए "मुख्य" और "यूई" धागे समान नहीं होते हैं।

+1

पर प्रकाश डाला गया हिस्सा इस जवाब के लिए धन्यवाद का एक छोटा सा भार। मैं कई बार आश्चर्यचकित हूं कि लोगों के पास इतनी अद्भुत खुदाई कौशल कैसे है और इसे बढ़ावा देना है। मैं समझता हूं कि सिस्टम ऐप्स की बात आने पर ये दोनों धागे स्पष्ट रूप से भिन्न होते हैं, हालांकि अलग-अलग यूई धागे पर कई विचार होने पर मैं कुछ समझने की कोशिश कर रहा हूं। क्या कोई तरीका है कि हम इसमें अंतर्दृष्टि प्राप्त कर सकते हैं या क्या मुझे कुछ कार्डिनल याद आ रही है। थ्रेडिंग मॉडल पर स्पष्टता के लिए हालांकि आपके लिए पूर्ण अंक। मैं इसे प्रश्न के प्राथमिक उद्देश्य के उत्तर के रूप में चिह्नित करूंगा लेकिन मेरे प्रश्न के दूसरे भाग पर कोई विचार? – humblerookie

+1

@ हम्बलरुकी, गर्म शब्दों के लिए धन्यवाद। सभी सिस्टम ऐप्स विशेष "मुख्य" थ्रेड का उपयोग नहीं करते हैं - उनमें से अधिकतर केवल नियमित ऐप्स हैं जिनके पास सिस्टम ऑरसिग्नेचर अनुमति समूह तक पहुंच है। यह सिस्टम ऐप है (वह जो पूरे फोन के रूट 'व्यू' को प्रस्तुत करता है) जिसे विशेष रूप से कॉन्फ़िगर किया गया "मुख्य" थ्रेड चाहिए। – Vasiliy

+4

@ हम्बलरुकी, और कई धागे पर यूआई के लिए, यह ऐसा कुछ नहीं है जिसे आप नियमित एप्लिकेशन (यहां तक ​​कि सिस्टम एप्लिकेशन भी नहीं) के साथ प्राप्त कर सकते हैं - यूआई थ्रेड एक प्रति ऐप है।हालांकि, इस व्यवहार को कई अनुप्रयोगों के साथ हासिल किया जा सकता है: चूंकि प्रत्येक ऐप का अपना यूआई थ्रेड होता है, इसलिए एप वाई से ऐप एक्स में परिभाषित 'सेवा' को बांधना संभव है, और तब ऐप वाई ऐप एक्स और ऐप एक्स को कमांड भेज सकता है यूआई प्रस्तुत करें। हालांकि इस तरह की एक योजना (जैसे कस्टम कीगार्ड) के लिए उपयोग के मामले हैं, यह व्यापक नहीं है। – Vasiliy

0

जब कोई एप्लिकेशन लॉन्च किया जाता है, तो सिस्टम "मुख्य" नामक एप्लिकेशन के निष्पादन का धागा बनाता है। यह धागा बहुत महत्वपूर्ण है क्योंकि यह घटनाओं को चित्रित करने सहित उचित उपयोगकर्ता इंटरफ़ेस विजेट्स को ईवेंट भेजने का प्रभारी है। यह वह धागा भी है जिसमें आपका एप्लिकेशन एंड्रॉइड यूआई टूलकिट (एंड्रॉइड.विजेट और एंड्रॉइड.व्यू पैकेज से घटक) से घटकों के साथ इंटरैक्ट करता है। इस प्रकार, मुख्य धागे को कभी-कभी यूआई थ्रेड भी कहा जाता है।

इस ट्यूटोरियल दस्तावेज़ पढ़ें। https://developer.android.com/guide/components/processes-and-threads.html#Threads

1

एंड्रॉइड में, "मुख्य" एप्लिकेशन थ्रेड को कभी-कभी UI थ्रेड कहा जाता है। मुख्य थ्रेड के बारे में आधिकारिक एपीआई से

उद्धरण:

[...] धागा, जिसमें आपके आवेदन एंड्रॉयड यूआई टूलकिट से घटकों (android.widget और android.view संकुल से घटकों के साथ सूचना का आदान प्रदान)। इस प्रकार, मुख्य धागे को कभी-कभी यूआई थ्रेड भी कहा जाता है।

सरकारी एपीआई पाया here.

2

सरल जवाब है भी यूआई सूत्र में आपका मुख्य थ्रेड।

जैसे, मुख्य थ्रेड भी है कभी कभी यूआई धागा कहा जाता है। जैसा कि प्रक्रियाओं और थ्रेड के एंड्रॉइड प्रलेखन के थ्रेड हिस्से में बताया गया है। Android Documentation

इसके अलावा, यूआई टूलकिट सुरक्षित थ्रेड नहीं है और कार्यकर्ता धागे के साथ पेश नहीं किया जाना चाहिए। मैं फिर से Android Documentation के हवाले कर रहा हूँ के रूप में यह Android के लिए संदर्भ गाइड है कि:

इस प्रकार, बस Android के एकल थ्रेड मॉडल के लिए दो नियम हैं:

1.Do यूआई धागा ब्लॉक नहीं

2।UI थ्रेड

के बाहर से एंड्रॉइड यूआई टूलकिट तक न पहुंचें आशा है कि मैं जो जवाब देता हूं उसका उत्तर दें।

1

सबसे सरल उदाहरण यह है: एक एंड्रॉइड सेवा मुख्य थ्रेड पर चलता है लेकिन सेवा में उपयोगकर्ता इंटरफ़ेस नहीं होता है। आप मुख्य थ्रेड को यूआई-थ्रेड के रूप में यहां कॉल नहीं कर सकते हैं।

Sqounk

संबंधित मुद्दे