Toast -Quellcode -Implementierung
Toasteingang
Wenn wir die Toast -Eingabeaufforderungen in der Anwendung verwenden, tätigen wir im Allgemeinen einen einfachen Codeaufruf, wie unten gezeigt:
[Java] Sehen Sie sich die Codetablets an.
Toast.makeText (Kontext, msg, toast.length_short) .show ();
Maketext ist der Eingang des Toasts. Der Quellcode ist wie folgt (Frameworks/Base/Core/Java/Android/Widget/Toast.java):
Öffentlicher statischer Toast Maketext (Kontextkontext, Charsexusextext, int Dauer) {Toast -Ergebnis = neuer Toast (Kontext); Internet.R.Layout.Transient_Notification, NULL); Dauer;Aus dem Quellcode von Maketext können wir feststellen, dass die Layoutdatei von Toast transient_notification.xml in Frameworks/Base/Core/Res/Layout/transition_notification.xml ist:
<? Match_Parent "Android: Orientierung =" Vertical "Android: Background ="? "Wrap_Content" Android: layout_weight = "1" Android: layout_gravity = "center_horizontal" Android: textapperance = "@style/soolaperance Shadowradius = "2.75" /> < /linearlayout>
Die Layoutdatei des Systemtoasts ist sehr einfach, dh eine Textansicht wird in der Linearlayout des vertikalen Layouts platziert. Als nächstes folgen wir weiterhin der Messe () -Methode, um die Implementierung des Anzeigcodes nach dem Gründung des Layouts zu untersuchen:
public void show () {if (mnextView == null) {neue runTimeexception ("setView muss genannt"); ; Versuchen {service.enqueuetoast (pkg, tn, mduration);} catch (remoteException e) {// leer}} Es gibt zwei Punkte in der Showmethode, auf die wir achten müssen. (1) Was ist TN? (2) Die Rolle des InotificationManager -Dienstes. Setzen Sie mit diesen beiden Problemen unseren Toast -Quellcode fort.
TN Quellcode
Viele Fragen können die Antwort über den Quellcode finden. Die Implementierung des MTN im Konstruktor von Toast ist der Quellcode wie folgt:
Public toast (context context) {mcontext = context; () .GetInteger (com.android.internal.r.iinteger.config_toastdefaultgravity);};};Als nächstes beginnen wir vom Quellcode der TN -Klasse, um die Rolle von TN zu untersuchen. Der TN -Quellcode lautet wie folgt:
Private statische Klasse TN erweitert iTransitenotification. (); ; angemessen WindowManager.LayoutParams.type_toast; Params.PrivateFlags = windowManager.layoutParams.Private_flag_for_all_users; .post (mshow);} / ** * Planen Sie den rechten Thread plan. mhide);} public void handleshow () {if (locallogv) log.v (Tag, "Handle anzeigen:" + this + "mview =" + mview + "xtview =" + mnextView); {// Die alte Ansicht entfernen Sie bei Bedarf Handlungen (); (WindowManager) context.getSystemService (context.window_service); Final Int Gravity = Gravity.GetabSoluteGravity (Mgravity, config.GetLayoutDirection ()); (Gravity & Gravity.vertical_Gravity_Mask) getParent ()! Hinzufügen! (! SPATCHPOPULTAKTIONSBILDUNG (Ereignis); = NULL) {// nicht: polking () nur um zu mak. Versuchen Sie nicht zu stürzen. Durch den Quellcode können wir die Vererbungsbeziehung offensichtlich sehen. Es wird angenommen, dass die Leser die Grundlage für die Kommunikation zwischen Android -Prozess haben (nicht bekannt, eine Reihe von Blogs von Luo Shengyangs Kommunikation zur Kommunikation von Binderprozess zu lernen). Da TN für die Kommunikation zwischen den Prozess verwendet wird, ist es für uns leicht zu glauben, dass die spezifische Rolle der TN -Klasse das Rückrufobjekt der Toastklasse sein sollte. die TN -Klasse.
Die TN -Klasse wird von Itransitenotification.Stub, ItransientNotification.AIDL in Frameworks/Base/Core/Java/App/iTransientNotification.aidl erbter.
Paket Android.App;
Die ItransientNotification definiert zwei Methoden anzeigen () und hide (), und ihre spezifische Implementierung befindet sich in der TN -Klasse. Die Implementierung der TN -Klasse ist:
/ ***Zeitplan handelt in den rechten Thread* / @Override public void show () {if (locallogv) log.v (Tag, " + this); */ @Override public void hide () {if (locallogv) log.v (Tag, "Hide:" + this);Hier können wir wissen, dass die Implementierung von Toasts Show- und Versteckmethode auf dem Handler -Mechanismus basiert. Die Handler -Implementierung in der TN -Klasse lautet:
Final Handl Mhandler = New Handler ();
Darüber hinaus haben wir in der TN -Klasse keine Looper.Perpare () und Looper.loop () -Methoden gefunden. Es zeigt, dass Mhandler das Looper -Objekt des aktuellen Threads aufruft. Wenn wir uns im Haupt -Thread befinden (dh im UI -Thread), können wir die Toast.Maketext -Methode nach Belieben aufrufen, da das Android -System uns hilft, die Looper -Initialisierung des Haupt -Threads zu realisieren.但是 , 如果你想在子线程中调用 Toast. Wesen Das Erlernen des Handler -Mechanismus kann sich auf einen Blog verweisen, den ich zuvor geschrieben habe: http://blog.csdn.net/wzy_1988/article/details/38346637.
Folgen Sie weiterhin die Implementierung von Mshow und Mhide, die beide ausgeführt werden.
Final Runnable mshow = new Runnable () {@Override public void run () {Handleshow ();}}; Handleshow () mNextView = null;}}; Es ist zu erkennen, dass die tatsächliche Implementierung von Show und Fell darin besteht, die Methoden Handleshow () bzw. Handel () bzw. Handel () aufzurufen. Schauen wir uns die spezifische Implementierung von Handleshow () an:
public void handleshow () {if (mView! ) {context = mview.getContext ();} mwm = (windowManager) context.getSystemService (context.window_Service); .GetContext () .getResources (). .fill_horizontal) {mparams.horizontalweight = 1.0f;} if (Gravity & Gravity.vertical_Gravity_Mask) = MverticalMargin; Aus dem Quellcode wissen wir, dass Toast in AddView über WindowsManager geladen wird. Daher ist die Methode aus der Hide, von Natur aus WindowsManager, die REMEVIEW -Methode aufzurufen, um die Toastansicht zu entfernen.
Zusammenfassend lässt sich sagen, dass die TN -Klasse durch Analyse des Quellcode der TN -Klasse ein Rückrufobjekt ist, und andere Prozesse rufen die Messe- und Ausblenden -Methode der TN -Klasse auf, um die Anzeige und das Verschwinden dieses Toasts zu steuern.
NotificationManagerservice
Zurück zur Show -Methode der Toast -Klasse können wir sehen, dass der GetService hier aufgerufen wird, um den InotificationManager -Dienst zu erhalten.
Private statische InotificationManager SService;
Nach dem Erhalt des InotificationManager -Dienstes wurde die Enqueuetoast -Methode aufgerufen, um den aktuellen Toast in die Toast -Warteschlange des Systems zu bringen. Die Parameter des Pass sind PKG, TN und MDuration. Mit anderen Worten, wir verwenden Toast.Maketext (Kontext, MSG, Toast.length_Show) .show (), um einen Toast zu präsentieren. Das System ruft die Messe- und Ausblenden -Methode des Callback -Objekts TN auf, um den Toast anzuzeigen und auszublenden.
Die spezifische Implementierungsklasse der Inofiticanager -Schnittstelle hier ist die NotificationManagerService -Klasse, die sich in Frameworks/Base/Services/Java/Com/Server/NotificationManagervice.java befindet.
Lassen Sie uns zunächst die Funktionen von Toasts Eintritt in den Enqueuetoast analysieren.
Public void enQeueToast (String PKG, ItrensientNotification Callback, int Dauer) {// Packagename ist NULL oder TN -Klasse als NULL. ) ||. (Pkg, binder.getCallinging ()) &&! // (2) anzeigen, ob der Toast bereits intindex = i ndexoftoastlocked (PKG, Callback) hat; Get (index); endgültig int n = mtoastqueue.size (); ++; TOASTRECORD -Objekte und in mtoastqueue. ) Wenn der Index 0 ist, bedeutet dies, dass sich das aktuelle Eintragsteam im Team befindet. }}} Es ist zu sehen, dass ich einen kurzen Kommentar zum obigen Code gemacht habe. Der Code ist relativ einfach, aber es gibt 4 Punkte, die uns weiter besprechen müssen.
(1) Bestimmen Sie, ob es sich um den Systemtoast handelt. Wenn der Paketname des aktuellen Toasts "Android" ist, handelt es sich um den Systemtoast. Andernfalls können Sie auch die Methode isCallerSystem () aufrufen, um sie zu beurteilen. Der Implementierungsquellcode dieser Methode lautet:
Boolean isuidsystem (int uid) {endgültig int Appid = userHandle.getAppid (uid); ());} Der Quellcode von IscallerSystem ist relativ einfach, dh zu bestimmen, ob die UID des aktuellen Toastprozesses einer der Systeme_UID, 0, Telefon_UID ist, wenn dies der Fall ist, ist es der Systemtoast; Toast.
Unabhängig davon, ob es sich um einen Systemtoast handelt, lesen Sie den folgenden Quellcode durch, es ist zu erkennen, dass es zwei Hauptvorteile gibt:
Der Systemtoast kann definitiv in die Systemtoastwarteschlange eintreten, und es wird nicht von der schwarzen Liste gestoppt.
Der Systemtoast hat nicht die Größengrenze in der Systemtoastwarteschlange, während der von gewöhnliche PKG gesendete Toast die Mengengrenze in der System -Toast -Warteschlange aufweist.
(2) Sehen Sie, ob sich der Toast, der dem Team anvertraut werden soll, bereits in der Systemtoastwarteschlange befindet. Dies wird durch Vergleich von PKG und Rückruf erreicht.
Private indexoftoastlocked (String pkg, ItrensientNotification Callback) {Ibinder cbak = callback.asbinder (); ++) {toastrecord r = list.get (i); Durch den obigen Code können wir die Schlussfolgerung ziehen, dass das System diesen Toast als denselben Toast betrachtet, solange der PKG -Name des Toasts mit dem TN -Objekt übereinstimmt.
(3) Stellen Sie den aktuellen Toastprozess als Verarbeitung der Rezeption ein. Der Quellcode ist unten angezeigt:
Private void keepprocessalivaled (int pid) {int toastcount = 0; list.get (i); 'T passiert nicht.}} Die MAM = ActivityManAGernative.getDefault () nennt hier die SetProcessforder -Methode, um den aktuellen PID -Prozess in die Verarbeitung der Rezeption zu setzen, um sicherzustellen, dass sie nicht systematisch getötet wird. Dies erklärt auch, warum Toast auch angezeigt werden kann, wenn der aktuelle Aktivität abgeschlossen ist, da der aktuelle Prozess noch ausgeführt wird.
(4) Wenn der Index 0 ist, wird der Toast des Warteschlangenkopfes angezeigt. Der Quellcode lautet wie folgt:
Private void thexttoastlocked () {// toastrecord toastrecord record = mtoastqueue.get (0); (); die Liste und lassen Sie den Proce Int index = mtoastqueue.indexof (record); = mtoastqueue.get (0);} else {record = null;}}}}Das Rückrufobjekt von Toast ist das TN -Objekt. Schauen wir uns als nächstes einen Blick darauf an, warum die Anzeigetast des Systems Toast nur 2s oder 3,5s betragen kann. Das Prinzip ist, dass Sie nach dem Aufrufen der Show -Methode von TN Toast auf die ScheduletMellockLocked -Methode aufrufen müssen, um Toast zu verschwinden. (Wenn Sie Fragen haben: Um nicht zu sagen, dass die Versteckmethode des TN -Objekts, um Toast zu verschwinden und wir haben normalerweise unser Büro. 使用的 Toast 都会在当前 Aktivität 停留几秒。如何实现停留几秒呢?原理就是 停留几秒。如何实现停留几秒呢?原理就是 停留几秒。如何实现停留几秒呢?原理就是 停留几秒。如何实现停留几秒呢?原理就是 发送 发送 message_timeout 消息去调用 tn 对象的 verstecken 方法 但是这个消息会有一个 但是这个消息会有一个 Delay 延迟 , 这里 这里 这里 这里 这里 这里 这里 这里 这里 这里 这里 这里 这里 这里 这里 这里 这里 这里 这里也是用了 Handler 消息机制)。
Private statische int long_delay = 3500; Long Delay = R.Duration == Toast.length_Long?
Zunächst sahen wir, dass dies hier nicht die Nachricht von Message_Timeout direkt gesendet hat, aber es gab eine Verzögerung der Verzögerung. Die Zeit der Verzögerung von "Long Delay = R.Duration == Toast.length_Long? Long_dlay: Short_dlay;" 2s oder 3,5s. Es ist nutzlos, eine Dauer in der Toast.Maketext -Methode nach Belieben zu verabschieden.
Schauen wir uns als nächstes an, wie Message_Timeout -Nachrichten in WorkerHandler verarbeitet werden. Die Art des Mandler -Objekts ist WorkerHandler, der Quellcode lautet wie folgt:
Private Final Class WorkerHandler erweitert Handler {@Override public void Handlemessage (Message MSG) {Switch (msg.what) {case message_timeout: Handleti Meout (toastrecord) msg.obj;Es ist zu erkennen, dass die Meldungsverarbeitung des WorkRhandlers zum Message_Timeout -Typ die Handlertimeout -Methode aufgerufen wird.
Private void Handletimeout (ToastRecord Record) {synchronized (mtoastqueue) {int index = indexoftoastLocked (record.pkg, record.callback);Bestimmen Sie im Handletimeout -Code zunächst, ob das Toastrecord -Objekt, das verschwunden werden muss, in der Warteschlange ist. Die Wahrheit ist kurz davor, vor uns zu erscheinen, weiterhin den Quellcode zu verfolgen:
Private void canceltoastlocked (int index) {toastrecord record = mtoastqueue.get (index); // Die Liste} mtoastqueue.remove (Index); Die Liste, so dass sich die Liste nach diesem Punkt nicht geändert hat. Haha, siehe hier wurde auch die Versteckmethode unseres Callback -Objekts aufgerufen und wird auch von mtoastqueue von mtoastqueue entfernt. Zu diesem Zeitpunkt ist das vollständige Display und das Verschwinden von Toast vorbei.