असाधारण रूप से दिलचस्प प्रश्न के लिए धन्यवाद।
बाहर निकलता है, यूआई और मुख्य धागे जरूरी नहीं हैं। हालांकि, जैसा कि आपने उद्धृत दस्तावेज में बताया है, भेद केवल कुछ सिस्टम अनुप्रयोगों (ओएस के हिस्से के रूप में चलाने वाले अनुप्रयोगों) के संदर्भ में महत्वपूर्ण है। इसलिए, जब तक आप कस्टम निर्माताओं का निर्माण नहीं करते हैं या फोन निर्माताओं के लिए एंड्रॉइड को अनुकूलित करने पर काम करते हैं, तो मैं किसी भी भेद को परेशान नहीं करता।
विस्तृत उत्तर:
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()
पर एक स्थिर कॉल करता है और प्राप्त संदर्भ संग्रहीत करता है। लेकिन इसका "यूई" थ्रेड ओवरराइड नहीं है, इसलिए "मुख्य" और "यूई" धागे समान नहीं होते हैं।
को क्रेडिट कृपया इस लिंक http://stackoverflow.com/questions/3261370/is-main-thread-the-same-as-ui-thread – Swapnil
कि does not मेरे सवाल और जवाब के माध्यम से जाना विशेष रूप से – humblerookie