Heim  >  Artikel  >  Web-Frontend  >  Fragen im Vorstellungsgespräch für Fortgeschrittene und Fortgeschrittene mit Android (mit Antworten)

Fragen im Vorstellungsgespräch für Fortgeschrittene und Fortgeschrittene mit Android (mit Antworten)

藏色散人
藏色散人nach vorne
2020-07-31 13:59:065417Durchsuche

Empfohlen: „Zusammenfassung der Android-Interviewfragen 2020 [Sammlung]

1, java in == und equals und hashCode

Die == verglichenen Werte der Basisdatentypen sind gleich Die == verglichenen Speicheradressen der

Klassen, Das heißt, ob es sich um dasselbe Objekt handelt, ohne die Speicheradresse zu überschreiben, z. B. String usw., die die Methode equals überschreibt.
hashCode ist ebenfalls eine Methode des Objekts Klasse. Gibt eine diskrete ganze Zahl zurück. Wird bei Erfassungsvorgängen verwendet, um die Abfragegeschwindigkeit zu verbessern. (HashMap, HashSet usw. vergleichen, ob sie gleich sind)

Wenn zwei Objekte gleich sind, geht die Java-Laufzeitumgebung davon aus, dass ihre Hashcodes gleich sein müssen.

Wenn zwei Objekte nicht gleich sind, können ihre Hashcodes gleich sein.

Wenn die Hashcodes zweier Objekte gleich sind, sind sie nicht unbedingt gleich.

Wenn die Hashcodes zweier Objekte nicht gleich sind, dürfen sie nicht gleich sein.

2, die Differenz zwischen int und integer

int Basistyp

Integer Object Int Kapselungsklasse

3, String , StringBuffer, StringBuilderDifference

String: Zeichen String-Konstanten eignen sich nicht für Situationen, in denen der Wert häufig geändert werden muss. Jede Änderung entspricht der Generierung eines neuen Objekts.

StringBuffer: String-Variable (Thread-sicher)
StringBuilder: String-Variable (Thread-unsicher) Stellen Sie sicher, dass ein einzelner Wert vorhanden ist. Thread-Operation Verfügbar, etwas effizienter als StringBuffer

4 Was ist eine interne Klasse? Die Rolle innerer Klassen

Innere Klassen können direkt auf die Eigenschaften externer Klassen zugreifen

Innere Klassen sind in Java hauptsächlich in
innere Mitgliedsklassen unterteilt , Lokale innere Klasse (in Methoden und Bereichen verschachtelt), Anonyme innere Klasse (kein Konstruktor), Statische innere Klasse (statisch modifizierte Klasse, kann keine Non verwenden -statische Mitgliedsvariablen und Methoden peripherer Klassen, hängen nicht von peripheren Klassen ab)

5, der Unterschied zwischen Prozessen und Threads

Prozess ist die kleinste Einheit der CPU-Ressourcenzuweisung und Thread ist die kleinste Einheit der CPU-Planung.

Prozesse können keine Ressourcen gemeinsam nutzen, aber Threads teilen sich den Adressraum und andere Ressourcen des Prozesses, in dem sie sich befinden.
Ein Prozess kann mehrere Threads haben und ein Prozess kann einen Prozess oder einen Thread starten.
Ein Thread kann nur zu einem Prozess gehören. Threads können Ressourcen desselben Prozesses direkt nutzen.

6, endgültig, endlich, abschließen

final: Klassen, Mitgliedsvariablen und Mitgliedsmethoden können nicht vererbt werden, Mitgliedsvariablen sind unveränderlich und Mitgliedsmethoden können nicht überschrieben werden

Abschließend: Wird zusammen mit try...catch... verwendet, um sicherzustellen, dass es unabhängig davon aufgerufen werden kann, ob eine Ausnahme auftritt.
finalize: Methode der Klasse. Diese Methode wird vor der Garbage Collection aufgerufen override finalize() Methoden zur Realisierung des Ressourcenrecyclings

7, Serializable und Parcelable Der Unterschied

Die serialisierbare Java-Serialisierungsschnittstelle generiert während des Lese- und Schreibvorgangs auf der Festplatte eine große Anzahl temporärer Variablen und führt eine große Anzahl von i aus /o-Operationen intern ausführen, was sehr ineffizient ist.

Parcelable Android-Serialisierungsschnittstelle ist effizient und mühsam beim Lesen und Schreiben im Speicher (AS verfügt über entsprechende Plug-Ins, um die erforderlichen Methoden mit einem Klick zu generieren), und Objekte können nicht auf der Festplatte gespeichert werden

8 Können statische Eigenschaften und statische Methoden vererbt werden? Kann es umgeschrieben werden? Und warum?

Vererbbar, nicht überschreibbar, aber ausgeblendet

Wenn statische Methoden und Attribute in der Unterklasse definiert sind, werden die statischen Methoden oder Attribute der übergeordneten Klasse zu diesem Zeitpunkt als „versteckt“ bezeichnet. Wenn Sie die statischen Methoden und Eigenschaften der übergeordneten Klasse aufrufen möchten, tun Sie dies direkt über den Namen, die Methode oder den Variablennamen der übergeordneten Klasse.

9, Verständnis der inneren Klassen von Mitgliedern, statischen inneren Klassen, lokalen inneren Klassen und anonymen inneren Klassen und Anwendung im Projekt

ava Interne Klassen werden hauptsächlich in

interne Mitgliedsklassen , lokale interne Klassen (in Methoden und Bereichen verschachtelt), anonyme interne Klassen (kein Konstruktor) und unterteilt Statische innere Klasse (Eine statisch modifizierte Klasse kann keine nicht statischen Mitgliedsvariablen und Methoden einer äußeren Klasse verwenden und ist nicht von äußeren Klassen abhängig)

Der attraktivste Grund für die Verwendung innerer Klassen ist: jedes Jeder Die innere Klasse kann unabhängig eine Implementierung (der Schnittstelle) erben. Ob also die äußere Klasse eine Implementierung (der Schnittstelle) geerbt hat, hat keinen Einfluss auf die innere Klasse.

Da Java keine Mehrfachvererbung unterstützt, unterstützt es die Implementierung mehrerer Schnittstellen. Manchmal gibt es jedoch einige Probleme, die mithilfe von Schnittstellen nur schwer zu lösen sind. Zu diesem Zeitpunkt können wir die von internen Klassen bereitgestellten Funktionen nutzen, um diese Programmierprobleme zu lösen. Man kann sagen, dass Schnittstellen nur einen Teil des Problems lösen und innere Klassen die Lösung der Mehrfachvererbung vollständiger machen.

10, String wird in GanzzahlMethode und PrinzipString →integer Intrger.parseInt(string);

Integer→string Integer.toString();

11

, Unter welchen Umständen werden Objekte durch den Garbage-Collection-Mechanismus entsorgt? 1. Alle Instanzen haben keinen aktiven Thread-Zugriff.

2. Eine zirkuläre Referenzinstanz, auf die keine andere Instanz zugreift.

3. In Java gibt es verschiedene Referenztypen. Ob eine Instanz für die Garbage Collection geeignet ist, hängt von ihrem Referenztyp ab.

Um festzustellen, welche Art von Objekten nutzlose Objekte sind. Hier gibt es zwei Methoden:

1. Verwenden Sie die Markierungszählmethode:

Wenn das Objekt einmal referenziert wird, wird die Anzahl um 1 erhöht wird freigegeben. Der Zähler wird um eins verringert. Wenn der Zähler 0 erreicht, kann das Objekt recycelt werden. Dies wirft natürlich auch ein Problem auf: Objekte mit Zirkelverweisen können nicht identifiziert und recycelt werden. Es gibt also eine zweite Methode:

2. Verwenden Sie den Root-Suchalgorithmus:

Beginnen Sie bei einem Root und suchen Sie nach allen erreichbaren Objekten, sodass die verbleibenden Objekte recycelt werden müssen

12

, der Unterschied zwischen statischem Proxy und dynamischem Proxy, in welchen Szenarien werden sie verwendet? Statische Proxy-Klasse: Von Programmierern erstellt oder automatisch von bestimmten Tools generiert und dann kompiliert. Bevor das Programm ausgeführt wird, ist die .class-Datei der Proxy-Klasse bereits vorhanden. Dynamische Proxy-Klasse: Wird dynamisch mithilfe des Reflexionsmechanismus erstellt, wenn das Programm ausgeführt wird.

14

, Was ist der Mechanismus zur Implementierung von Polymorphismus in Java? Antwort: Überschreiben und Überladen von Methoden sind verschiedene Erscheinungsformen des Java-Polymorphismus

Überschreiben ist ein Teil des Polymorphismus zwischen Eltern- und Unterklassen. Eine Erscheinungsform

Überladen ist eine Manifestation von Polymorphismus in einer Klasse

16

, sagen Sie mir, was Sie über Java denkenVerständnis von Reflexion

Der JAVA-Reflexionsmechanismus befindet sich im laufenden Zustand. Für jede Klasse können Sie alle Eigenschaften und Methoden dieser Klasse kennen und jede ihrer Methoden und Eigenschaften aufrufen. Ausgehend vom Objekt können Sie durch Reflexion (Klassenklasse) die vollständigen Informationen der Klasse (Klassenname, Klassentyp, Paket, alle Methodentypen Method[] und vollständige Informationen einer Methode (einschließlich Modifikatoren, Rückgabewerttyp) erhalten , Ausnahme, Parametertyp), alle Attribute Field[], vollständige Informationen eines bestimmten Attributs, Konstruktoren), Aufruf der Attribute oder Methoden der Klasse selbst Zusammenfassung: Erhalten Sie alle Informationen der Klasse, des Objekts und der Methode während des laufenden Prozesses .

17, sprechen Sie über Ihr Verständnis von JavaAnmerkungen

Meta-Annotation

Die Rolle der Meta-Annotation besteht darin, andere Anmerkungen zu kommentieren. In Java 5.0 wurden vier Standard-Meta-Annotationstypen definiert, die zur Beschreibung anderer Annotationstypen verwendet werden.

1.@Target

2.@Retention

3.@Dokumentiert

4.@Inherited

18 Verstehen von , JavaString

In Im Quellcode wird die Zeichenfolge mit final geändert, einer Konstante, die nicht geändert oder vererbt werden kann.

19, StringWarum sollte es unveränderlich gestaltet sein?

1. Anforderungen für den String-Pool

Der String-Pool ist ein spezieller Speicherbereich im Methodenbereich. Wenn eine Zeichenfolge erstellt wurde und sich im Pool befindet, wird sofort ein Verweis auf die Zeichenfolge an die Variable zurückgegeben, anstatt die Zeichenfolge neu zu erstellen und die Referenz auf die Variable zurückzugeben. Wenn Zeichenfolgen nicht unveränderlich sind, führt eine Änderung der Zeichenfolge in einer Referenz (z. B. Zeichenfolge2) zu fehlerhaften Daten in einer anderen Referenz (z. B. Zeichenfolge1).

2. String-Cache-Hashcodes zulassen

Hashcodes von Strings werden häufig in Java verwendet, wie zum Beispiel: HashMap. Die Unveränderlichkeit von String stellt sicher, dass der Hash-Code immer derselbe ist, sodass er sich keine Gedanken über Änderungen machen muss. Dieser Ansatz bedeutet, dass der Hash-Code nicht bei jeder Verwendung neu berechnet werden muss – was wesentlich effizienter ist.

3. Sicherheit

String wird häufig für Parameter in Java-Klassen verwendet, z. B.: Netzwerkverbindung (Netzwerkverbindung), Öffnen von Dateien (Öffnen von Dateien) usw. Wenn String nicht unveränderlich ist, werden Netzwerkverbindungen und Dateien geändert – dies führt zu einer Reihe von Sicherheitsrisiken. Man ging davon aus, dass die Funktionsweise an eine Maschine gekoppelt sei, aber in Wirklichkeit war das nicht der Fall. Da es sich bei den reflektierten Parametern ausschließlich um Zeichenfolgen handelt, führt dies auch zu einer Reihe von Sicherheitsproblemen.

20, Objekt Klassen gleich und hashCode Methode überschreibt, warum?

Zuallererst ist die Beziehung zwischen gleich und Hashcode wie folgt:

1 Wenn zwei Objekte gleich sind (das heißt, sie werden mit gleich verglichen und geben „true“ zurück), dann ihre HashCode-Werte müssen gleich sein;

2 Wenn der HashCode zweier Objekte gleich ist, sind sie nicht unbedingt gleich (das heißt, ein Vergleich mit „equals“ gibt „false“ zurück)

Da die Hashcode-Methode implementiert wird, um die Effizienz des Programms zu verbessern, fahren Sie zunächst fort. Wenn der Hashcode-Vergleich unterschiedlich ist, ist kein Gleichheitsvergleich erforderlich, was die Anzahl der Gleichheitsvergleiche im Vergleich zur großen Anzahl von Vergleichen erheblich verringert , die Effizienzsteigerung ist offensichtlich

21 Der Unterschied zwischen , Liste, Satz, Karte

Set ist die einfachste Art von Sammlung. Die Objekte in der Sammlung sind nicht auf eine bestimmte Weise geordnet und es gibt keine doppelten Objekte. Die Set-Schnittstelle implementiert hauptsächlich zwei Implementierungsklassen: HashSet: Die HashSet-Klasse greift gemäß dem Hash-Algorithmus auf Objekte im Set zu, und die Zugriffsgeschwindigkeit ist relativ hoch

TreeSet: Die TreeSet-Klasse implementiert die SortedSet-Schnittstelle und kann Zugriff auf die Objekte im Satz. Objekte werden sortiert.

Das Merkmal der Liste besteht darin, dass ihre Elemente linear gespeichert werden und wiederholte Objekte in der Sammlung gespeichert werden können.

ArrayList(): stellt ein Array dar, dessen Länge geändert werden kann. Auf Elemente kann nach dem Zufallsprinzip zugegriffen werden, und das Einfügen und Löschen von Elementen in ArrayList() ist langsam.

LinkedList(): Verwendet die Datenstruktur einer verknüpften Liste in der Implementierung. Das Einfügen und Löschen erfolgt schnell, der Zugriff ist langsam.

Map ist eine Sammlung, die Schlüsselobjekte und Wertobjekte zuordnet. Jedes Element davon enthält ein Paar von Schlüsselobjekten und Wertobjekten. Map erbt nicht von der Collection-Schnittstelle. Beim Abrufen von Elementen aus der Map-Sammlung wird das entsprechende Wertobjekt zurückgegeben, solange das Schlüsselobjekt angegeben ist.

HashMap: Kartenbasierte Implementierung der Hash-Tabelle. Die Kosten für das Einfügen und Abfragen von Schlüssel-Wert-Paaren sind festgelegt. Die Kapazität und der Ladefaktor können über den Konstrukteur eingestellt werden, um die Leistung des Containers anzupassen.

LinkedHashMap: Ähnlich wie HashMap, aber beim Durchlaufen ist die Reihenfolge, in der die „Schlüssel-Wert-Paare“ erhalten werden, ihre Einfügereihenfolge oder die am wenigsten kürzlich verwendete Reihenfolge (LRU). Nur geringfügig langsamer als HashMap. Der iterative Zugriff ist schneller, da zur Aufrechterhaltung der internen Reihenfolge eine verknüpfte Liste verwendet wird.

TreeMap: Implementierung basierend auf der rot-schwarzen Baumdatenstruktur. Beim Anzeigen von „Schlüsseln“ oder „Schlüssel-Wert-Paaren“ werden diese sortiert (die Reihenfolge wird durch Comparabel oder Comparator bestimmt). Das Besondere an TreeMap ist, dass die Ergebnisse sortiert sind. TreeMap ist die einzige Map mit einer subMap()-Methode, die einen Teilbaum zurückgeben kann.

WeakHashMao: Schwacher Schlüssel Map, die in der Map verwendeten Objekte dürfen auch freigegeben werden: Dies dient der Lösung spezieller Probleme. Wenn außerhalb der Karte kein Verweis auf einen „Schlüssel“ vorhanden ist, kann dieser „Schlüssel“ vom Garbage Collector recycelt werden.

26 Vergleich von ArrayMap und HashMap

1. Verschiedene Speichermethoden

In HashMap wird jedes Schlüssel-Wert-Paar gespeichert Die Put-Methode fügt ein Schlüssel-Wert-Paar hinzu. Es wird ein neues HashMapEntry-Objekt erstellt. 2. Beim Hinzufügen von Daten ist die Verarbeitung beim Erweitern unterschiedlich. was sehr teuer ist. ArrayMap verwendet Kopierdaten, daher ist die Effizienz relativ hoch.

3. ArrayMap bietet die Funktion zur Array-Verkleinerung. Nach dem Löschen oder Entfernen wird das Array wieder verkleinert, unabhängig davon, ob Platz vorhanden ist oder nicht.

29 Der Unterschied zwischen

,

HashMap und HashTable 1 HashMap ist nicht threadsicher. Es ist effizienter und die Methode ist nicht synchronisiert. Es gibt die Methoden „containsvalue“ und „containsKey“. Hashtable ist threadsicher und lässt keine Nullschlüssel und -werte zu. Es ist etwas weniger effizient und die Methode ist Synchronize. Es gibt Methoden. Hashtable erbt von den Wörterbuchklassen

30

,

HashMap und HashSet Unterschied hashMap: HashMap implementiert die Map-Schnittstelle. Verwenden Sie die Methode put(), um Elemente in die Karte einzufügen .Value, HashMap ist schneller, da zum Abrufen von Objekten eindeutige Schlüssel verwendet werden. HashSet implementiert nur Objekte, um Elemente in den Satz einzufügen. Die Hashcodes können daher für zwei Objekte gleich sein Die Methode „equals“ wird verwendet, um die Gleichheit von Objekten zu bestimmen. Wenn die beiden Objekte unterschiedlich sind, wird „false“ zurückgegeben. HashSet ist langsamer als HashMap.

31

,

HashSet und HashMap So ermitteln Sie, ob Elemente festgelegt sind sind dupliziert? HashSet kann keine doppelten Elemente hinzufügen. Wenn die Methode add (Object) aufgerufen wird, ruft zunächst die hashCode-Methode von Object auf, um festzustellen, ob der hashCode bereits vorhanden ist Wenn es nicht existiert, wird es direkt eingefügt. Wenn es bereits vorhanden ist, wird die Methode „equals“ des Objekts aufgerufen. Wenn es „true“ ist, ist das Element bereits vorhanden .

33 Auch die Unterschiede zwischen

,

ArrayList und LinkedList als Anwendungsszenario ArrayList wird basierend auf Arrays implementiert und ArrayList ist threadunsicher. LinkedList wird basierend auf einer doppelt verknüpften Liste implementiert:

Verwendungsszenarien:

(1) Wenn die Anwendung jeweils eine große Anzahl von Zugriffs- oder Löschvorgängen für Elemente ausführt Indexposition, ArrayList-Objekte sind LinkedList-Objekten weit überlegen

(2) Wenn die Anwendung hauptsächlich Listen durchläuft und während der Schleife Einfüge- oder Löschvorgänge ausführt, sind LinkedList-Objekte ArrayList-Objekten weit überlegen;

34

, Der Unterschied zwischen Arrays und verknüpften Listen

Array: Es speichert Elemente kontinuierlich im Speicher; seine Vorteile: Da die Daten kontinuierlich gespeichert werden Die Speicheradresse ist kontinuierlich und daher effizienter bei der Suche nach Daten. Ihr Nachteil: Vor dem Speichern müssen wir einen kontinuierlichen Speicherplatz beantragen und die Größe dieses Speicherplatzes muss während der Kompilierung bestimmt werden. Die Größe des Speicherplatzes kann während des Betriebs nicht entsprechend Ihren Anforderungen geändert werden. Wenn die Daten relativ groß sind, kann es sein, dass sie verschwendet werden. Beim Ändern der Datenanzahl sind das Hinzufügen, Einfügen und Löschen von Daten weniger effizient. Verknüpfte Liste: Es handelt sich um eine dynamische Anwendung für den Speicherplatz. Sie muss die Speichergröße nicht im Voraus beantragen, wie bei einem Array. Eine verknüpfte Liste muss nur dann angewendet werden, wenn sie verwendet wird Für die Datenerweiterung und das Löschen und Einfügen sind sie flexibler als Arrays. Hinzu kommt, dass sich die Daten in der verknüpften Liste an einer beliebigen Stelle im Speicher befinden können und die Daten über die Anwendung (d. h. über den Zeiger des vorhandenen Elements) verknüpft werden

35

, Thread starten Drei Wege?

Ava bietet drei Möglichkeiten, Threads zu erstellen, nämlich die Thread-Klasse zu erben, die Runable-Schnittstelle zu implementieren und den Thread-Pool zu verwenden

36 Was ist der Unterschied zwischen Thread und Prozess?

Threads sind eine Teilmenge von Prozessen. Ein Prozess kann viele Threads haben und jeder Thread führt unterschiedliche Aufgaben parallel aus. Verschiedene Prozesse nutzen unterschiedliche Speicherplätze und alle Threads teilen sich denselben Speicherplatz. Verwechseln Sie dies nicht mit dem Stapelspeicher. Jeder Thread verfügt über einen eigenen Stapelspeicher zum Speichern lokaler Daten.

38, run() und start() Methodenunterschiede

Diese Frage wird oft gestellt, kann aber dennoch das Verständnis des Interviewers für das Java-Thread-Modell unterscheiden. Die start()-Methode wird verwendet, um einen neu erstellten Thread zu starten, und start() ruft intern die run()-Methode auf, was einen anderen Effekt hat als der direkte Aufruf der run()-Methode. Wenn Sie die Methode run() aufrufen, wird sie nur im ursprünglichen Thread aufgerufen. Wenn kein neuer Thread gestartet wird, startet die Methode start() einen neuen Thread.

39 Wie steuere ich die Anzahl gleichzeitiger Zugriffsthreads, die eine Methode zulässt?

semaphore.acquire() fordert ein Semaphor an. Zu diesem Zeitpunkt beträgt die Anzahl der Semaphoren -1 (sobald kein verwendbares Semaphor vorhanden ist, d. h. wenn die Anzahl der Semaphoren negativ wird, fordern Sie erneut an wird blockiert, bis andere Threads das Semaphor freigeben)

semaphore.release() gibt ein Semaphor frei und die Anzahl der Semaphore + 1 zu diesem Zeitpunkt

40 , der Unterschied zwischen den Methoden wait und seelp in Java ;

Sowohl Warten als auch Schlafen in Java-Programmen führen zu einer Art Pause und können unterschiedliche Anforderungen erfüllen. Die Methode „wait()“ wird für die Kommunikation zwischen Threads verwendet. Wenn die Wartebedingung wahr ist und andere Threads aktiviert werden, wird die Sperre aufgehoben, während die Methode „sleep()“ nur CPU-Ressourcen freigibt oder den aktuellen Thread für einen Zeitraum von anhält Zeit, hebt die Sperre jedoch nicht auf.

41, sprechen Sie über das Verständnis von Warten/BenachrichtigenSchlüsselwörtern

Warten auf die Synchronisationssperre des Objekts. Sie müssen die Synchronisationssperre des Objekts erhalten, bevor Sie diese Methode aufrufen. Andernfalls kann die Kompilierung erfolgreich sein, es wird jedoch zur Laufzeit eine Ausnahme empfangen: IllegalMonitorStateException.

Der Aufruf der Methode wait() eines beliebigen Objekts führt dazu, dass der Thread blockiert, die Ausführung des Threads nicht fortgesetzt werden kann und die Sperre für das Objekt aufgehoben wird.

Wenden Sie den Thread auf, der auf die Synchronisationssperre des Objekts wartet (wecken Sie nur einen, wenn mehrere warten). Beachten Sie, dass Sie beim Aufrufen dieser Methode nicht genau einen Thread im Wartezustand aufwecken können. Stattdessen bestimmt die JVM, welcher Thread aktiviert werden soll, und nicht anhand der Priorität.

Der Aufruf der notify()-Methode eines beliebigen Objekts führt dazu, dass ein zufällig ausgewählter Thread durch den Aufruf der wait()-Methode des Objekts blockiert wird, um die Blockierung aufzuheben (diese wird jedoch erst ausgeführt, wenn die Sperre erreicht ist).

42 Was verursacht Thread-Blockierung? Wie schließe ich den Thread?

Die Blockierungsmethode bedeutet, dass das Programm auf den Abschluss der Methode wartet, ohne etwas anderes zu tun. Die Methode „accept()“ von ServerSocket wartet darauf, dass der Client eine Verbindung herstellt. Das Blockieren bedeutet hier, dass der aktuelle Thread angehalten wird, bevor das Aufrufergebnis zurückgegeben wird, und erst dann zurückkehrt, wenn das Ergebnis erhalten wird. Darüber hinaus gibt es asynchrone und nicht blockierende Methoden, die vor Abschluss der Aufgabe zurückkehren.

Eine besteht darin, die stop()-Methode darin aufzurufen

Die andere besteht darin, eine Markierung zu setzen, um den Thread selbst zu stoppen (empfohlen)

43 , Wie kann die Thread-Sicherheit gewährleistet werden?

1. Synchronisiert;

2. Warten Sie, benachrichtigen Sie den ThreadLocal-Mechanismus.

44

Wie erreicht man eine Thread-Synchronisierung? 1. So ändern Sie das synchronisierte Schlüsselwort. 2. Anweisungsblöcke, die durch das synchronisierte Schlüsselwort geändert werden. 3. Verwenden Sie spezielle Domänenvariablen (flüchtig), um eine Thread-Synchronisation zu erreichen

45

, Inter-Thread-Operationen Liste List list = Collections.synchronizedList(new ArrayList());

46

, sprechen Sie über Synchronized Verstehen von Schlüsselwörtern, Klassensperren, Methodensperren und Wiedereintrittssperren Javas Objektsperren und Klassensperren: Javas Objektsperren und Klassensperren sind in Sperren Das Konzept ist im Grunde dasselbe wie die integrierte Sperre, aber die beiden Sperren werden tatsächlich für Objektinstanzmethoden oder für eine Objektinstanz verwendet, und Klassensperren werden für statische Methoden von Klassen oder für die Klasse verwendet Objekt einer Klasse. Wir wissen, dass es viele Objektinstanzen einer Klasse geben kann, jede Klasse jedoch nur ein Klassenobjekt hat, sodass sich die Objektsperren verschiedener Objektinstanzen nicht gegenseitig stören, es jedoch nur eine Klassensperre für jede Klasse gibt. Es muss jedoch beachtet werden, dass die Klassensperre tatsächlich nur eine konzeptionelle Sache ist und nicht wirklich existiert. Sie dient nur dazu, den Unterschied zwischen Sperrinstanzmethoden und statischen Methoden zu verstehen

49 Der Unterschied zwischen , synchronisierten und flüchtigen Schlüsselwörtern

1. Volatile teilt dem JVM im Wesentlichen mit, dass der Wert der aktuellen Variablen im Register (Arbeitsspeicher) unsicher ist und aus dem Hauptspeicher gelesen werden muss Der aktuelle Thread kann auf diese Variable zugreifen, andere Threads werden blockiert.

2. Volatile kann nur auf Variablen-, Methoden- und Klassenebene verwendet werden.

3. Volatile kann nur die Änderungssichtbarkeit von Variablen erreichen garantieren Atomizitätsgeschlecht; während synchronisiert die Sichtbarkeit und Atomizität von Variablenänderungen garantieren kann

4.volatile verursacht keine Thread-Blockierung;

5. Variablen, die als flüchtig gekennzeichnet sind, werden vom Compiler nicht optimiert >ReentrantLock

, synchronisiert und volatil Vergleich Ava konnte den gegenseitigen Ausschluss in der Vergangenheit lange Zeit nur durch das synchronisierte Schlüsselwort erreichen, was einige Mängel aufweist. Sie können beispielsweise keine Methoden oder Blockgrenzen außerhalb der Sperre erweitern, Sie können beim Versuch, die Sperre zu erhalten, nicht auf halbem Weg abbrechen usw. Java 5 bietet eine komplexere Steuerung über die Lock-Schnittstelle, um diese Probleme zu lösen. Die ReentrantLock-Klasse implementiert Lock, das die gleiche Parallelität und Speichersemantik wie synchronisiert hat, aber auch erweiterbar ist. 53 Vier notwendige Bedingungen für einen Deadlock?

Ursachen für Deadlocks

1. Konkurrenz um Systemressourcen Konkurrenz um Systemressourcen führt zu unzureichenden Systemressourcen und falscher Ressourcenzuteilung, was zu einem Deadlock führt.

2. Die Reihenfolge der Prozessausführung ist unangemessen

Bedingung zum gegenseitigen Ausschluss: Eine Ressource kann jeweils nur von einem Prozess verwendet werden, das heißt, eine bestimmte Ressource kann nur von einem Prozess belegt werden innerhalb eines Zeitraums. Wenn zu diesem Zeitpunkt andere Prozesse die Ressource anfordern, kann der anfordernde Prozess nur warten.

Anforderungs- und Aufbewahrungsbedingungen: Der Prozess hat mindestens eine Ressource beibehalten, hat aber eine neue Ressourcenanforderung gestellt und die Ressource ist bereits von anderen Prozessen belegt hat keinen Zugriff auf die erhaltene Ressource. Die Ressourcen bleiben erhalten.

Unvermeidlichkeitsbedingung: Die von einem Prozess erhaltenen Ressourcen können von anderen Prozessen nicht zwangsweise weggenommen werden, bevor sie vollständig verwendet werden, dh sie können nur von dem Prozess freigegeben werden, der die Ressourcen erhalten hat (sie können nur freigegeben werden). aktiv).

Schleifenwartebedingungen: Mehrere Prozesse bilden eine End-to-End-Schleife, die auf Ressourcen wartet

Diese vier Bedingungen sind notwendige Bedingungen für einen Deadlock, solange im System ein Deadlock auftritt. Diese Bedingungen müssen erfüllt sein, solange eine der oben genannten Bedingungen nicht erfüllt ist.

Deadlock-Vermeidung und -Verhinderung:

Grundidee der Deadlock-Vermeidung:

Das System überprüft dynamisch die vom Prozess ausgegebenen Ressourcenanforderungen für jedes System, das erfüllt werden kann. und basierend auf Das Prüfergebnis bestimmt, ob Ressourcen zugewiesen werden sollen. Wenn das System nach der Zuweisung blockiert, wird es nicht zugewiesen, andernfalls wird es zugewiesen. Dies ist eine dynamische Strategie, um sicherzustellen, dass das System nicht in einen Deadlock-Zustand gerät.

Wenn Sie die Ursachen von Deadlocks verstehen, insbesondere die vier notwendigen Bedingungen für Deadlocks, können Sie Deadlocks weitestgehend vermeiden, verhindern und beseitigen. Achten Sie daher im Hinblick auf Systemdesign und Prozessplanung darauf, wie Sie sicherstellen können, dass diese vier notwendigen Bedingungen nicht zutreffen, und wie Sie einen angemessenen Ressourcenzuweisungsalgorithmus festlegen, um zu vermeiden, dass Prozesse dauerhaft Systemressourcen belegen. Darüber hinaus muss verhindert werden, dass Prozesse im Wartezustand Ressourcen belegen. Daher muss die Ressourcenallokation richtig geplant werden.

Der Unterschied zwischen Deadlock-Vermeidung und Deadlock-Verhinderung:

Deadlock-Verhinderung besteht darin, zu versuchen, mindestens eine der vier notwendigen Bedingungen für Deadlocks zu zerstören, das Auftreten von Deadlocks strikt zu verhindern und die Lock-Vermeidung zu verhindern schränkt das Vorhandensein notwendiger Bedingungen für einen Deadlock nicht strikt ein, denn selbst wenn die notwendigen Bedingungen für einen Deadlock vorliegen, muss ein Deadlock nicht unbedingt auftreten. Bei der Vermeidung von Deadlocks ist darauf zu achten, dass während des Betriebs des Systems möglicherweise kein Deadlock auftritt.

56

Was ist ein Thread-Pool und wie wird er verwendet?

?

Das Erstellen von Threads kostet teure Ressourcen und Wenn der Thread erst erstellt wird, nachdem die Aufgabe eintrifft, wird die Antwortzeit länger und die Anzahl der Threads, die von einem Prozess erstellt werden können, ist begrenzt. Um diese Probleme zu vermeiden, werden mehrere Threads erstellt, die beim Start des Programms auf die Verarbeitung reagieren. Sie werden Thread-Pools genannt, und die darin enthaltenen Threads werden Arbeits-Threads genannt. Ab JDK1.5 stellt die Java-API das Executor-Framework bereit, sodass Sie verschiedene Thread-Pools erstellen können. Beispielsweise verarbeitet ein einzelner Thread-Pool jeweils eine Aufgabe; eine feste Anzahl von Thread-Pools oder ein Cache-Thread-Pool (ein skalierbarer Thread-Pool, der für Programme mit vielen kurzlebigen Aufgaben geeignet ist). 57

Was ist der Unterschied zwischen Heap und Stack in Java

?

Warum wird diese Frage als Interviewfrage zu Multithreading und Parallelität klassifiziert? Weil der Stapel ein Speicherbereich ist, der eng mit Threads verbunden ist. Jeder Thread verfügt über einen eigenen Stapelspeicher, der zum Speichern lokaler Variablen, Methodenparameter und Stapelaufrufe verwendet wird. Variablen, die in einem Thread gespeichert sind, sind für andere Threads nicht sichtbar. Der Heap ist ein gemeinsamer Speicherbereich, der von allen Threads gemeinsam genutzt wird. Alle Objekte werden im Heap erstellt, um die Effizienz zu verbessern. Wenn mehrere Threads diese Variable verwenden, kann dies zu Problemen führen. Der Thread muss vom Hauptstapel aus starten und den Wert einer Variablen aus dem Speicher lesen.

58, es gibt drei Threads T1, T2, T3, wie kann sichergestellt werden, dass sie in der richtigen Reihenfolge ausgeführt werden?

Beim Multithreading gibt es viele Möglichkeiten, Threads in einer bestimmten Reihenfolge ausführen zu lassen. Sie können die Methode „join()“ der Thread-Klasse verwenden, um einen anderen Thread in einem Thread zu starten Thread schließt den Thread ab und fährt mit der Implementierung fort. Um die Reihenfolge der drei Threads sicherzustellen, sollten Sie den letzten Thread zuerst starten (T3 ruft T2 auf, T2 ruft T1 auf), sodass T1 zuerst und T3 zuletzt beendet wird.

Inter-Thread-Kommunikation

Wir wissen, dass Threads die kleinste Einheit der CPU-Planung sind. In Android kann der Hauptthread keine zeitaufwändigen Vorgänge ausführen und Unterthreads können die Benutzeroberfläche nicht aktualisieren. Es gibt viele Möglichkeiten, zwischen Threads zu kommunizieren, z. B. Broadcast, Eventbus und Schnittstellenrückrufe. In Android werden hauptsächlich Handler verwendet. Der Handler sendet die Nachricht, die die Nachricht enthält, durch Aufrufen der sendmessage-Methode an die Messagequeue, und das Looper-Objekt ruft kontinuierlich die Schleifenmethode auf, um die Nachricht aus der Messagequeue zu nehmen und sie zur Verarbeitung an den Handler zu übergeben, wodurch die Kommunikation zwischen Threads abgeschlossen wird .

Thread-Pool

Es gibt vier gängige Thread-Pools in Android: FixedThreadPool, CachedThreadPool, ScheduledThreadPool und SingleThreadExecutor.

Der FixedThreadPool-Thread-Pool wird über die neue FixedThreadPool-Methode von Executors erstellt. Sein Merkmal ist, dass die Anzahl der Threads im Thread-Pool fest ist. Selbst wenn Threads inaktiv sind, werden sie nicht recycelt, es sei denn, der Thread-Pool wird geschlossen. Wenn alle Threads aktiv sind, warten neue Aufgaben in der Warteschlange auf die Verarbeitung durch Threads. Beachten Sie, dass FixedThreadPool nur Kernthreads und keine Nicht-Kernthreads hat.

Der CachedThreadPool-Thread-Pool wird durch den newCachedThreadPool von Executors erstellt. Es handelt sich um einen Thread-Pool mit einer variablen Anzahl von Threads. Er hat keine Kern-Threads, sondern nur Nicht-Kern-Threads. Wenn alle Threads im Thread-Pool aktiv sind, werden neue Threads erstellt, um neue Aufgaben zu erledigen. Andernfalls werden inaktive Threads zur Bearbeitung neuer Aufgaben verwendet. Die Threads im Thread-Pool verfügen über einen Timeout-Mechanismus. Der Timeout-Mechanismus beträgt 60 Sekunden. Nach dieser Zeit werden inaktive Threads recycelt. Diese Art von Thread-Pool eignet sich für die Bearbeitung großer Mengen an Aufgaben, die weniger Zeit in Anspruch nehmen. Es sollte hier erwähnt werden, dass die Aufgabenwarteschlange von CachedThreadPool grundsätzlich leer ist.

Der ScheduledThreadPool-Thread-Pool wird über den newScheduledThreadPool von Executors erstellt. Seine Kern-Threads sind festgelegt, aber die Anzahl der Nicht-Kern-Threads ist nicht festgelegt. Wenn die Nicht-Kern-Threads inaktiv sind, werden sie sofort recycelt . Diese Art von Thread eignet sich zum Ausführen geplanter Aufgaben und wiederkehrender Aufgaben mit einem festen Zeitraum.

Der SingleThreadExecutor-Thread-Pool wird über die newSingleThreadExecutor-Methode von Executors erstellt. Es gibt nur einen Kern-Thread in diesem Thread-Pool-Typ und keine Nicht-Kern-Threads. Dadurch wird sichergestellt, dass alle Aufgaben im selben Thread ausgeführt werden können und in der richtigen Reihenfolge, sodass keine Thread-Synchronisierungsprobleme berücksichtigt werden müssen.

So funktioniert AsyncTask

AsyncTask ist eine leichte asynchrone Aufgabenklasse, die von Android selbst bereitgestellt wird. Es kann Hintergrundaufgaben im Thread-Pool ausführen und dann den Ausführungsfortschritt und die Endergebnisse an den Hauptthread weitergeben, um die Benutzeroberfläche zu aktualisieren. Tatsächlich kapselt AsyncTask Thread und Handler intern. Obwohl AsyncTask zum Ausführen von Hintergrundaufgaben und zum Aktualisieren der Benutzeroberfläche im Hauptthread sehr praktisch ist, eignet sich AsyncTask nicht für besonders zeitaufwändige Hintergrundvorgänge. Für besonders zeitaufwändige Aufgaben empfehle ich persönlich die Verwendung eines Thread-Pools.

AsyncTask bietet 4 Kernmethoden:

1. onPreExecute(): Diese Methode wird im Hauptthread ausgeführt und vor der Ausführung der asynchronen Aufgabe aufgerufen. Sie wird im Allgemeinen für einige Vorbereitungsarbeiten verwendet .

2. doInBackground(String... params): Diese Methode wird im Thread-Pool ausgeführt. Diese Methode wird verwendet, um asynchrone Aufgaben auszuführen. Bei dieser Methode kann der Fortschritt der Aufgabe über die Methode „publishProgress“ aktualisiert werden. Darüber hinaus wird das Ergebnis der Aufgabe an die Methode „onPostExecute“ zurückgegeben.

3. onProgressUpdate(Object... Values): Diese Methode wird im Hauptthread ausgeführt und hauptsächlich verwendet, wenn der Aufgabenfortschritt aktualisiert wird.

4. onPostExecute(Long aLong): Wird im Hauptthread ausgeführt. Die Parameter dieser Methode sind die Rückgabeergebnisse des Hintergrunds.

Zusätzlich zu diesen Methoden gibt es auch einige weniger häufig verwendete Methoden, wie z. B. onCancelled(), die aufgerufen wird, wenn die asynchrone Aufgabe abgebrochen wird.

Aus dem Quellcode können wir erkennen, dass die MethodeexecuteOnExecutor() aus der obigen Ausführungsmethode aufgerufen wird, d. h.executeOnExecutor(sDefaultExecutor, params); und sDefaultExecutor ist tatsächlich ein serieller Thread-Pool. Hier wird die Methode onPreExecute() aufgerufen. Schauen Sie sich als Nächstes diesen Thread-Pool an. Die Ausführung von AsyncTask wird aufgrund des Schlüsselworts „synchonized“ in die Warteschlange gestellt und der Params-Parameter von AsyncTask ist in der FutureTask-Klasse gekapselt. Die FutureTask-Klasse ist eine gleichzeitige Klasse und fungiert hier als Runnable. Anschließend wird die FutureTask zur Verarbeitung an die Ausführungsmethode von SerialExecutor übergeben, und die Executor-Methode von SerialExecutor fügt die FutureTask zunächst zur mTasks-Warteschlange hinzu. Wenn zu diesem Zeitpunkt keine Aufgabe vorhanden ist, wird die Methode ScheduleNext () aufgerufen die nächste Aufgabe ausführen. Wenn eine Aufgabe vorhanden ist, wird am Ende nach der Ausführung ScheduleNext(); aufgerufen, um die nächste Aufgabe auszuführen. bis alle Aufgaben erledigt sind. Im Konstruktor von AsyncTask gibt es eine call()-Methode, die von der run-Methode von FutureTask ausgeführt wird. Letztendlich wird diese Aufrufmethode also im Thread-Pool ausgeführt. Hier wird die Methode doInBackground aufgerufen. Schauen wir uns diese call()-Methode genauer an. mTaskInvoked.set(true); zeigt an, dass die aktuelle Aufgabe ausgeführt wurde. Führen Sie dann die Methode doInBackground aus und übergeben Sie das Ergebnis schließlich über die Methode postResult(result); In der postResult()-Methode werden Nachrichten über sHandler gesendet. In sHandler wird ein MESSAGE_POST_RESULT anhand des Nachrichtentyps beurteilt. In diesem Fall wird die Methode onPostExecute(result) oder onCancelled(result) aufgerufen. Ein weiterer Nachrichtentyp ist MESSAGE_POST_PROGRESS, der onProgressUpdate aufruft, um den Fortschritt zu aktualisieren.

Binder Arbeitsmechanismus

Intuitiv ist Binder eine Klasse in Android, die die IBinder-Schnittstelle implementiert. Im Allgemeinen ist Binder ist eine Möglichkeit der prozessübergreifenden Kommunikation in Android. Es kann auch als virtuelles physisches Gerät verstanden werden, und sein Gerätetreiber ist /dev/binder/. Aus Framework-Sicht ist Binder die Brücke von ServiceManager. Auf der Anwendungsebene ist Binder das Medium für die Kommunikation zwischen dem Client und dem Server.

Lassen Sie uns zunächst die Bedeutung jeder Methode in dieser Klasse verstehen:

DESCRIPTOR: Binders eindeutiger Bezeichner, der im Allgemeinen zur Darstellung des aktuellen Binder-Klassennamens verwendet wird.

asInterface(android.os.IBinder obj): Wird verwendet, um das Binder-Objekt des Servers in das vom Client benötigte AIDL-Schnittstellentypobjekt zu konvertieren Befindet sich der Client im selben Prozess, gibt diese Methode das Stub-Objekt des Servers selbst zurück, andernfalls gibt sie das systemgekapselte Stub.proxy-Objekt zurück.

asBinder(): wird verwendet, um das aktuelle Binder-Objekt zurückzugeben.

onTransact: Diese Methode wird im Binder-Thread-Pool auf der Serverseite ausgeführt. Wenn der Client eine prozessübergreifende Kommunikationsanforderung initiiert, wird die Remote-Anfrage von der untersten Schicht des Systems gekapselt und an diese Methode übergeben zur Bearbeitung. Achten Sie auf diese Methode: public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel Reply, int flags). Der Server kann die vom Client angeforderte Zielmethode über den Code ermitteln und dann das Ziel abrufen aus den Daten, die von der Methode benötigt werden, und führen Sie dann die Zielmethode aus. Wenn die Zielmethode ausgeführt wird, wird der Rückgabewert als Antwort geschrieben. So wird die Methode ausgeführt. Wenn diese Methode „false“ zurückgibt, schlägt der Client die Anfrage fehl, sodass wir bei dieser Methode eine gewisse Sicherheitsüberprüfung durchführen können.

Binders Arbeitsmechanismus, aber es gibt einige Punkte, auf die man achten muss: 1. Wenn der Kunde eine Anfrage initiiert, weil Der aktuelle Thread wird angehalten, bis der Server Daten zurückgibt. Wenn diese Remote-Methode sehr zeitaufwändig ist, kann diese Remote-Anfrage nicht im UI-Thread, also im Haupt-Thread, initiiert werden.

2. Da die Binder-Methode von Service im Thread-Pool ausgeführt wird, sollte die Binder-Methode synchronisiert werden, unabhängig davon, ob sie zeitaufwändig ist oder nicht, da sie bereits in einem Thread ausgeführt wird. Wir alle wissen es dass die Implementierung aus drei Teilen besteht: onMeasure(), onLayout() und onDraw(). Der Zeichenprozess von View beginnt mit der perfromTraversal-Methode von viewRoot. Es kann die Ansicht mithilfe der Mess-, Layout- und Zeichenmethoden zeichnen. Unter anderem misst „measure“ die Breite und Höhe, „layout“ bestimmt die Position der Ansicht im übergeordneten Container und „draw“ zeichnet die Ansicht auf den Bildschirm.

Messung:Anzeigemessung erfordert MeasureSpc (Messspezifikation), das einen 32-Bit-Int-Wert darstellt, die oberen 2 Bits stellen SpecMode (Messmodus) dar und Die niedrigen (30) Bits repräsentieren SpecSize (Spezifikationsgröße in einem bestimmten Messmodus). Ein Satz von SpecMode und SpeSize kann in eine MeasureSpec gepackt werden, und umgekehrt kann MeasureSpec entpackt werden, um die Werte von SpecMode und SpeSize zu erhalten. Es gibt drei Arten von SpecMode: unSpecified: Der übergeordnete Container unterliegt keinen Einschränkungen hinsichtlich der Ansicht, egal wie groß oder klein er sein möchte. Dies wird hauptsächlich in allgemeinen Systemen verwendet.

Genau: Der übergeordnete Container hat die genaue Größe erkannt, die die Ansicht erfordert. Zu diesem Zeitpunkt ist die Größe der Ansicht der durch SpecSize angegebene Wert, der math_parent im Layout oder dem spezifischen Wert

At_most: Der übergeordnete Container gibt eine SpecSize der verfügbaren Größe an. Er entspricht dem wrao_content in diesem Layout Die MeasureSpec des übergeordneten Containers und sich selbst. Das LayoutParam wird gemeinsam bestimmt. Sobald die MeasureSpec bestimmt ist, kann onMeasure die Breite und Höhe der Ansicht bestimmen.

Messprozess der Ansicht:

Die onMeasure-Methode verfügt über eine setMeasureDimenSion-Methode zum Festlegen des Breiten- und Höhenmesswerts der Ansicht, und setMeasureDimenSion verfügt über eine getDefaultSize()-Methode als Parameter. Unter normalen Umständen müssen wir nur auf die Situationen „at_most“ und „exact“ achten. Der Rückgabewert von getDefaultSize ist SpecSize in MeasureSpec, und dieser Wert ist im Grunde die gemessene Größe der Ansicht. Im Fall von UnSpecified handelt es sich im Allgemeinen um einen Messprozess innerhalb des Systems, der Faktoren wie den Hintergrund der Ansicht berücksichtigen muss.

Worüber wir zuvor gesprochen haben, ist der Messprozess von view und der Messprozess von viewGroup:

Für viewGroup muss zusätzlich zum Abschluss des eigenen Messprozesses auch ein Durchlauf zum Aufruf erfolgen Bei der Measure-Methode der Unterklasse führt jedes untergeordnete Element diesen Prozess rekursiv aus. viewGroup ist eine abstrakte Klasse, die keine onMeasure-Methode, sondern eine MeasureChildren-Methode bereitstellt. Die Idee der MeasureChild-Methode besteht darin, die LayoutParams des untergeordneten Elements herauszunehmen, dann die MeasureSpec des untergeordneten Elements über getChildMeasureSpec abzurufen und dann das untergeordnete Element in der Elektrophorese-Messmethode zu messen. Da viewGroup-Unterklassen unterschiedliche Layoutmethoden haben, sind ihre Messdetails unterschiedlich, sodass viewGroup die onMeasure-Methode nicht für messungsähnliche Ansichten aufrufen kann.

Hinweis: Es gibt keine Möglichkeit, die Breite und Höhe der Ansicht während des Aktivitätslebenszyklus korrekt zu ermitteln. Der Grund dafür ist, dass die Ansicht nicht gemessen wurde.

Wird in der onWindowFocuschanged-Methode abgerufen ---- Die Bedeutung der geänderten Methode besteht darin, dass die Ansicht mit der

    View.post()-Methode initialisiert wurde, an die die Nachricht übermittelt wird das Ende der Nachrichtenwarteschlange.
  1. Verwenden Sie zum Abschluss den Rückruf von viewTreeObserver.
  2. Manuell messen über view.measure.
  3. onLayout

Für eine normale Ansicht können Sie die setFrame-Methode verwenden, um die Position der vier Scheitelpunkte der Ansicht abzurufen, die auch die Position bestimmt der Ansicht im übergeordneten Container und rufen Sie dann die Methode onLayout auf, die die Position des untergeordneten Elements aus dem übergeordneten Container bestimmt.

onDraw

Diese Methode zeichnet die Ansicht auf den Bildschirm. Unterteilen Sie sich in folgende Schritte:

Hintergrund zeichnen,

    sich selbst zeichnen,
  1. Kind zeichnen,
  2. Dekoration zeichnen.
  3. Leistungsoptimierung in Android

Aufgrund der Einschränkungen der Mobiltelefon-Hardware können weder der Speicher noch die CPU so groß sein Bei Android-Telefonen kann eine übermäßige Speichernutzung leicht zu OOM führen, und eine übermäßige Nutzung der CPU-Ressourcen kann dazu führen, dass das Telefon einfriert oder sogar Probleme verursacht. Ich optimiere hauptsächlich aus den folgenden Teilen:

Layoutoptimierung, Zeichnungsoptimierung, Speicherverlustoptimierung, Antwortgeschwindigkeitsoptimierung, Listenansichtsoptimierung, Bitmapoptimierung, Threadoptimierung

Layoutoptimierung: Tool Hierarchyviewer, Lösung:

1. Löschen Sie nutzlose Räume und Ebenen.

2. Wählen Sie eine Ansichtsgruppe mit geringerer Leistung, z. B. Relativelayout oder LinearLayout, verwenden Sie zuerst LinearLayout, da die Relativelayout-Funktion relativ komplex ist und mehr CPU-Ressourcen beansprucht.

3. Verwenden Sie die Tags 2b2ce02883c1666e919b0f20335eaf2a, um das Layout wiederzuverwenden, fecc3e51a9f4ddea0b0a0fe6cfb27c34, um es vorab zu laden und nur dann zu laden, wenn es verwendet wird.

Zeichnungsoptimierung

Zeichnungsoptimierung bedeutet, dass die Ansicht eine große Anzahl zeitaufwändiger Vorgänge in der Ondraw-Methode vermeidet, da die Ondraw-Methode möglicherweise häufig aufgerufen wird.

1. Erstellen Sie keine neuen lokalen Variablen in der Ondraw-Methode. Die Ondraw-Methode wird häufig aufgerufen, was leicht zu GC führen kann.

2. Führen Sie keine zeitaufwändigen Vorgänge in der Ondraw-Methode durch.

Speicheroptimierung: Referenzspeicherverlust.

Antwortoptimierung: Der Hauptthread kann keine zeitaufwändigen Vorgänge ausführen, Berührungsereignisse dauern 5 Sekunden, Übertragungen dauern 10 Sekunden und Dienste dauern 20 Sekunden.

Listview-Optimierung:

1. Vermeiden Sie zeitaufwändige Vorgänge in der getview-Methode.

2. Wiederverwendung von Ansichten und Verwendung durch Betrachter.

3. Sliding ist nicht geeignet, um asynchrones Laden zu ermöglichen.

4. Daten durch Paging verarbeiten.

5. Bilder verwenden den Cache der Stufe drei.

Bitmap-Optimierung:

1. Komprimieren Sie Bilder in gleichen Proportionen.

2. Nicht verwendete Bilder rechtzeitig recyceln

Thread-Optimierung

Die Idee der Thread-Optimierung besteht darin, den Thread-Pool zum Verwalten und Wiederverwenden von Threads zu verwenden, um eine große Anzahl zu vermeiden Threads im Programm können auch die Anzahl gleichzeitiger Threads steuern, um Thread-Blockierungen aufgrund der gegenseitigen Bevorzugung von Ressourcen zu vermeiden.

Weitere Optimierungen

1. Verwenden Sie weniger Aufzählungen, die viel Platz beanspruchen.

2. Verwenden Sie Android-spezifische Datenstrukturen wie SparseArray anstelle von hashMap.

3. Verwenden Sie weiche und schwache Referenzen angemessen.

Verschlüsselungsalgorithmen (

base64, MD5, symmetrische Verschlüsselung und asymmetrische Verschlüsselung) und Nutzungsszenarien. Was ist Rsa-Verschlüsselung?

Der RSA-Algorithmus ist der beliebteste Verschlüsselungsalgorithmus mit öffentlichen Schlüsseln und verwendet Schlüssel, deren Länge variieren kann. RSA ist der erste Algorithmus, der sowohl für die Datenverschlüsselung als auch für digitale Signaturen verwendet werden kann.

Das Prinzip des RSA-Algorithmus lautet wie folgt:

1. Wählen Sie zufällig zwei große Primzahlen p und q aus, p ist nicht gleich q, berechnen Sie

2. Wählen Sie eine Zahl größer als. Wenn 1 kleiner als N ist, muss die natürliche Zahl e teilerfremd sein mit (p-1)(q-1).

3. Verwenden Sie die Formel, um d zu berechnen: d×e = 1 (mod (p-1)(q-1)).

4. Zerstöre p und q.

Das letzte N und e sind der „öffentliche Schlüssel“ und d ist der „private Schlüssel“. Der Sender verwendet N zum Verschlüsseln der Daten, und der Empfänger kann d nur zum Entschlüsseln des Dateninhalts verwenden.

Die Sicherheit von RSA beruht auf der Zerlegung großer Zahlen. N kleiner als 1024 Bit hat sich als unsicher erwiesen. Da der RSA-Algorithmus Berechnungen mit großen Zahlen durchführt, ist RSA schneller als DES. Dies ist der größte Wert Fehler von RSA, daher kann es normalerweise nur zum Verschlüsseln kleiner Datenmengen oder Verschlüsselungsschlüssel verwendet werden, aber RSA ist immer noch ein hochleistungsfähiger Algorithmus.

Verwendungsszenarien: Im Projekt wird mit Ausnahme von Anmelde-, Zahlungs- und anderen Schnittstellen die asymmetrische RSA-Verschlüsselung und für andere Schnittstellen die symmetrische AES-Verschlüsselung verwendet. Heute erfahren Sie mehr über die AES-Verschlüsselung.

Was ist MD5-Verschlüsselung?

Der vollständige englische Name von MD5 lautet „Message-Digest Algorithm 5“, was übersetzt „Message Digest Algorithm 5“ bedeutet. Es ist ein Einweg-Verschlüsselungsalgorithmus irreversible Verschlüsselungsmethode.

Was sind die Merkmale der MD5-Verschlüsselung?

Kompressibilität: Für jede Datenlänge ist die Länge des berechneten MD5-Werts festgelegt.

Einfach zu berechnen: Der MD5-Wert lässt sich leicht aus den Originaldaten berechnen.

Änderungsbeständigkeit: Wenn Änderungen an den Originaldaten vorgenommen werden, selbst wenn nur 1 Byte geändert wird, wird der resultierende MD5-Wert sehr unterschiedlich sein.

Starke Antikollision: Angesichts der Originaldaten und ihres MD5-Werts ist es sehr schwierig, Daten mit demselben MD5-Wert (dh gefälschte Daten) zu finden.

MD5-Anwendungsszenarien:

Konsistenzüberprüfung

Digitale Signatur

Sichere Zugriffsauthentifizierung

Was ist AES-Verschlüsselung?

Advanced Encryption Standard (englisch: Advanced Encryption Standard, Abkürzung: AES), in der Kryptographie auch als Rijndael-Verschlüsselung bekannt, ist ein Blockverschlüsselungsstandard, der von der US-Bundesregierung übernommen wurde. Dieser Standard ersetzt den ursprünglichen DES. Er wurde von vielen Parteien analysiert und ist weltweit weit verbreitet.

HashMap-Implementierungsprinzip:

HashMap ist eine asynchrone Implementierung der Map-Schnittstelle auf Basis von Hash-Tabellen, die die Verwendung von Nullwerten als Schlüssel und Wert ermöglicht. In der Programmiersprache Java gibt es zwei grundlegendste Strukturen: eine ist ein Array und die andere ist ein simulierter Zeiger (Referenz). Alle Datenstrukturen können mit diesen beiden Grundstrukturen erstellt werden, und HashMap bildet da keine Ausnahme. HashMap ist eigentlich eine „Linked-List-Hash“-Datenstruktur. Das ist eine Kombination aus Array und verknüpfter Liste.

Die unterste Ebene von HashMap ist eine Datenstruktur und jedes Element im Array ist eine verknüpfte Liste.

Konflikt:

Die Hashcode()-Methode wird in HashMap aufgerufen, um den Hashclde-Wert zu berechnen, da zwei verschiedene Objekte in Java möglicherweise denselben Hashcode haben. Dies führte zu Konflikten.

Lösung:

Wenn HashMap eingefügt wird, kann der zugrunde liegende Quellcode angezeigt werden. Wenn das Programm versucht, ein Schlüsselwertobjekt in eine HashMap einzufügen, gibt es zunächst den Wert entsprechend zurück hashCode() des Schlüssels. Wenn der Rückgabewert der hashCode()-Methode der beiden Eintragsschlüssel gleich ist, sind ihre Speicherorte identisch. Wenn die beiden Eintragsschlüssel durch einen Gleichheitsvergleich zurückgegeben werden , wird der Wert des neu hinzugefügten Eintrags den Wert des ursprünglichen Eintrags überschreiben, aber der Schlüssel wird nicht überschrieben. Im Gegenteil, wenn false zurückgegeben wird, bildet der neu hinzugefügte Eintrag eine Eintragskette mit dem ursprünglichen Eintrag in Sammlung, mit dem neu hinzugefügten am Kopf und dem alten am Ende

Das Implementierungsprinzip von HashMap:

  1. Verwenden Sie den HashCode des Schlüssels, um den Index erneut aufzubereiten und zu berechnen des Elements des aktuellen Objekts im Array.
  2. Wenn während der Speicherung Schlüssel mit demselben Hashwert auftauchen, gibt es zwei Situationen: 1. Wenn die Schlüssel gleich sind, wird der ursprüngliche Wert überschrieben. 2. Wenn die Schlüssel unterschiedlich sind (Konflikt auftritt), fügen Sie sie in die verknüpfte Liste ein.
  3. Suchen Sie beim Abrufen direkt den Index, der dem Hash-Wert entspricht, und bestimmen Sie dann weiter, ob der Schlüssel derselbe ist, um den entsprechenden Wert zu erhalten.
  4. Der Kern von Hashmap besteht darin, ein Array zur Speicherung zu verwenden. Wenn ein Schlüsselkonflikt auftritt, wird dieser in einer verknüpften Liste gespeichert.

============================

1 ?

onCreate() -> onResume() -> onStop() -> ?

Es gibt zwei Möglichkeiten, den Dienst zu starten: Eine besteht darin, über startService() zu starten, die andere über bindService(). Verschiedene Startmethoden haben unterschiedliche Lebenszyklen.

Der Lebenszyklus eines über startService() gestarteten Dienstes ist wie folgt: call startService() --> onStartConmon()--> Wenn Sie auf diese Weise beginnen, müssen Sie zunächst auf mehrere Probleme achten: Wenn wir über startService aufgerufen werden und startService () mehrmals aufrufen, wird die Methode onCreate () nur einmal aufgerufen, und onStartConmon (). mehrmals aufgerufen werden. Wenn wir stopService() aufrufen, wird onDestroy() aufgerufen, um den Dienst zu zerstören. Zweitens: Wenn wir über startService starten, den Wert über die Absicht übergeben und den Wert in der Methode onStartConmon () abrufen, müssen wir zunächst feststellen, ob die Absicht null ist.

Binden Sie über bindService(). So binden Sie den Dienst, Lebenszyklusmethode: bindService-->onCreate()-->onBind()-->unBind()- ->onDestroy( ) bingservice Der Vorteil des Startens des Dienstes auf diese Weise besteht darin, dass es bequemer ist, den Dienst in der Aktivität zu betreiben. Es gibt beispielsweise mehrere Methoden, um dem Dienst beizutreten: a, b Wenn Sie ihn in der Aktivität aufrufen möchten Sie müssen das ServiceConnection-Objekt in der Aktivität abrufen. Verwenden Sie ServiceConnection, um das Klassenobjekt der internen Klasse im Dienst abzurufen, und verwenden Sie dann dieses Klassenobjekt, um Methoden in der Klasse aufzurufen Objekt

3. Aktivitätsstartvorgang (nicht auf den Lebenszyklus antworten)

Es gibt zwei Situationen im App-Startvorgang. Die erste besteht darin, auf das entsprechende Anwendungssymbol im Desktop-Launcher zu klicken. und die zweite besteht darin, eine neue Aktivität zu starten, indem startActivity in der Aktivität aufgerufen wird.

Wenn wir ein neues Projekt erstellen, ist die Standard-Stammaktivität MainActivity, und alle Aktivitäten werden im Stapel gespeichert. Wenn wir eine neue Aktivität starten, wird sie über der vorherigen Aktivität platziert und wir wann Wenn wir auf dem Desktop auf das Anwendungssymbol klicken, ruft das System beim Klicken auf das Symbol startActivitySately() auf. Unter normalen Umständen werden die relevanten Informationen der von uns gestarteten Aktivität in der Absicht gespeichert. wie Aktion, Kategorie usw. Wenn wir diese Anwendung installieren, startet das System auch einen PackaManagerService-Verwaltungsdienst. Dieser Verwaltungsdienst analysiert die Datei AndroidManifest.xml, um relevante Informationen in der Anwendung abzurufen, z. B. Dienst, Aktivität, Broadcast usw., und erhält dann Informationen darüber zugehörigen Komponenten. Wenn wir auf das Anwendungssymbol klicken, wird die Methode startActivitySately() aufgerufen, und innerhalb dieser Methode wird startActivty() aufgerufen, und die Methode startActivity() ruft schließlich die Methode startActivityForResult() auf. Und in der startActivityForResult()-Methode. Da die Methode startActivityForResult() ein Ergebnis zurückgibt, gibt das System direkt eine -1 aus, was bedeutet, dass kein Ergebnis zurückgegeben werden muss. Die Methode startActivityForResult() startet die Aktivität tatsächlich über die Methode execStartActivity() in der Instrumentation-Klasse. Die Hauptfunktion der Instrumentation-Klasse besteht darin, die Interaktion zwischen dem Programm und dem System zu überwachen. In dieser execStartActivity()-Methode wird das Proxy-Objekt von ActivityManagerService abgerufen und die Aktivität wird über dieses Proxy-Objekt gestartet. Beim Start wird eine checkStartActivityResult()-Methode aufgerufen. Wenn diese Komponente nicht in der Konfigurationsliste konfiguriert ist, wird in dieser Methode eine Ausnahme ausgelöst. Als letztes muss natürlich Application.scheduleLaunchActivity() aufgerufen werden, um die Aktivität zu starten. In dieser Methode wird ein ActivityClientRecord-Objekt abgerufen, und dieser ActivityClientRecord verwendet den Handler, um Nachrichten zu senden intern. Beschreibung, und das ActivityClientRecord-Objekt speichert ein LoaderApk-Objekt, über das handleLaunchActivity aufgerufen wird, um die Aktivitätskomponente zu starten, und die Lebenszyklusmethode der Seite wird in dieser Methode aufgerufen.

4. Broadcast-Registrierungsmethoden und Unterschiede

Erweiterung hier: Wann sollte die dynamische Registrierung verwendet werden

Broadcast-Broadcast, es gibt zwei Hauptregistrierungsmethoden.

Die Die erste ist die statische Registrierung, die auch zu einer residenten Übertragung werden kann. Die auf diese Weise registrierte Übertragung ist vom Seitenlebenszyklus nicht betroffen Dennoch wird der Empfang einer Sendung im Allgemeinen verwendet, wenn Sie den Computer automatisch starten möchten usw. Da die Sendung bei dieser Registrierungsmethode eine permanente Sendung ist, werden CPU-Ressourcen beansprucht.

Der zweite Typ ist die dynamische Registrierung. Diese Registrierungsmethode wird auch als nicht residente Übertragung bezeichnet. Nach dem Verlassen der Seite wird dies nicht der Fall sein Wenn wir die Übertragung empfangen, verwenden wir sie normalerweise, um die Benutzeroberfläche zu aktualisieren. Diese Registrierungsmethode hat eine höhere Priorität. Schließlich müssen Sie die Bindung aufheben, um Speicherverluste zu vermeiden.

Die Übertragung wird in geordnete Übertragung und ungeordnete Übertragung unterteilt.

5. Der Unterschied zwischen HttpClient und HttpUrlConnection

Erweiterung hier: Welche Anforderungsmethode wird in Volley verwendet (HttpClient vor 2.3, HttpUrlConnection nach 2.3)

Erstens unterstützen HttpClient und HttpUrlConnection beide das Https-Protokoll. Sie laden Daten in Form von Streams hoch. Man kann auch sagen, dass sie Daten in Form von Streams sowie IPv6, Verbindungspooling und anderen übertragen Funktionen. HttpClient verfügt über viele APIs. Wenn Sie es also erweitern möchten, ohne die Kompatibilität zu beeinträchtigen, hat Google diesen HttpClient in Android 6.0 direkt aufgegeben.

HttpUrlConnection ist relativ leichtgewichtig Es verfügt über relativ wenige APIs, ist leicht zu erweitern und kann die meisten Datenübertragungen von Android erfüllen. Volley, ein relativ klassisches Framework, verwendete HttpClient vor Version 2.3 und HttpUrlConnection nach Version 2.3.

6. Der Unterschied zwischen Java Virtual Machine und Dalvik Virtual Machine

Java Virtual Machine:

1 Die Java Virtual Machine basiert auf dem Stapel. Stapelbasierte Maschinen müssen Anweisungen zum Laden und Bearbeiten von Daten auf dem Stapel verwenden, und es sind weitere Anweisungen erforderlich.

2. Die Java Virtual Machine führt Java-Bytecode aus. (Java-Klassen werden in eine oder mehrere Bytecode-.class-Dateien kompiliert)

Dalvik Virtual Machine:

1. Die Dalvik Virtual Machine ist registerbasiert

2, Dalvik führt ein benutzerdefiniertes .dex-Bytecodeformat aus. (Nachdem die Java-Klasse in eine .class-Datei kompiliert wurde, wird ein dx-Tool verwendet, um alle .class-Dateien in eine .dex-Datei zu konvertieren, und dann liest die virtuelle Dalvik-Maschine Anweisungen und Daten daraus

3. Konstantenpool Wurde geändert, um nur 32-Bit-Indizes zu verwenden, um den Interpreter zu vereinfachen

4. Eine Anwendung, eine virtuelle Maschineninstanz und ein Prozess (alle Android-Anwendungsthreads entsprechen einem Linux-Thread, Alle laufen in einer eigenen Sandbox. Jede Android-Dalvik-Anwendung erhält eine unabhängige Linux-PID (app_*))

7. Prozess bleibt am Leben (undead-Prozess))

Erweiterung hier: Was ist die Priorität des Prozesses

Die aktuellen Keep-Alive-Methoden für Android-Prozesse sind hauptsächlich in drei Typen unterteilt: Schwarz, Weiß und Grau. Ihre grobe Implementierung Die Idee ist wie folgt:

Schwarzes Keep-Alive: Verschiedene App-Prozesse nutzen Broadcasts, um sich gegenseitig aufzuwecken (einschließlich der Nutzung der vom System bereitgestellten Broadcasts zum Aufwecken)

Weißes Keep-Alive: Starten Sie den Vordergrunddienst

Graues Keep-Alive: Nutzen Sie Systemschwachstellen, um den Vordergrunddienst zu starten

Schwarzes Keep-Alive

Das sogenannte Black-Keep-Alive besteht darin, unterschiedliche App-Prozesse zu verwenden, um jeden aufzuwecken Andere verwenden Broadcasts. Hier sind drei gängige Szenarien:

Szenario 1: Verwenden Sie die vom System generierte Übertragung, um die App beim Einschalten des Telefons, beim Wechseln des Netzwerks, beim Aufnehmen von Fotos oder beim Aufnehmen von Videos zu aktivieren.

Szenario 2: Durch die Verbindung mit einem SDK eines Drittanbieters wird auch die entsprechende App aktiviert. Der App-Prozess, z. B. das WeChat SDK, aktiviert WeChat und das Alipay SDK aktiviert Alipay. Daraus ergibt sich das folgende Szenario 3 direkt ausgelöst werden

Szenario 3: Wenn Sie Alipay und Taobao auf Ihrem Telefon, Tmall, UC und anderen Alibaba-basierten Apps installiert haben, werden nach dem Öffnen einer Alibaba-basierten App möglicherweise andere Alibaba aktiviert -basierte Apps übrigens (nehmen Sie einfach Alibaba als Beispiel, tatsächlich ist das BAT-System ähnlich

White Keep-Alive

Die White-Keep-Alive-Methode ist sehr einfach). Dabei wird die System-API aufgerufen, um einen Vordergrunddienstprozess zu starten. Dadurch wird eine Benachrichtigung in der Systembenachrichtigungsleiste generiert, um den Benutzer darüber zu informieren, dass eine solche App ausgeführt wird, auch wenn die aktuelle App wie gezeigt in den Hintergrund tritt Unten in LBE und QQ Music:

Gray Keep-Alive

Gray Keep-Alive, diese Art der Keep-Alive-Methode ist der weiteste Anwendungsbereich. Sie nutzt Systemschwachstellen, um a zu starten Der Unterschied zur normalen Startmethode besteht darin, dass in der Systembenachrichtigungsleiste keine Benachrichtigung angezeigt wird und es so aussieht, als ob ein Hintergrunddienstprozess ausgeführt wird. Der Vorteil besteht darin, dass der Benutzer nicht erkennen kann, dass Sie ausgeführt werden ein Vordergrundprozess (da die Benachrichtigung nicht sichtbar ist), aber Ihre Prozesspriorität ist höher als die von gewöhnlichen Hintergrundprozessen. Wie können also Systemschwachstellen ausgenutzt werden? Die allgemeinen Implementierungsideen und Codes lauten wie folgt:

Idee 1: API

Idee 2: API >= 18, zwei Front-End-Dienste mit derselben ID gleichzeitig starten und dann den später gestarteten Dienst stoppen

Kinder, die mit dem Android-System vertraut sind, wissen, dass das System ist Basierend auf Erfahrung und Leistungsüberlegungen wird das System den Prozess nicht wirklich beenden, wenn die App in den Hintergrund zurückkehrt, sondern ihn zwischenspeichern. Je mehr Anwendungen Sie öffnen, desto mehr Prozesse werden im Hintergrund zwischengespeichert. Wenn der Systemspeicher nicht ausreicht, beginnt das System anhand seiner eigenen Prozessrecyclingmechanismen zu bestimmen, welche Prozesse beendet werden müssen, um Speicher für die Bereitstellung benötigter Apps freizugeben. Dieser Mechanismus zum Beenden von Prozessen und zum Zurückgewinnen von Speicher wird als Low Memory Killer bezeichnet. Er basiert auf dem OOM Killer-Mechanismus (Out-Of-Memory Killer) des Linux-Kernels.

Die Bedeutung des Prozesses ist in 5 Ebenen unterteilt:

Vordergrundprozess (Foreground Process)

Sichtbarer Prozess (Visible Process)

Serviceprozess ( Serviceprozess) )

Hintergrundprozess

Leerer Prozess

Nachdem wir Low Memory Killer verstanden haben, erfahren wir mehr über oom_adj. Was ist oom_adj? Dies ist ein Wert, der jedem Systemprozess vom Linux-Kernel zugewiesen wird und die Priorität des Prozesses darstellt. Der Prozessrecyclingmechanismus bestimmt anhand dieser Priorität, ob er recycelt werden soll. Bezüglich der Rolle von oom_adj müssen Sie sich nur die folgenden Punkte merken:

Je größer der oom_adj des Prozesses ist, desto niedriger ist die Priorität des Prozesses und desto einfacher ist er zu töten und zu recyceln Je höher die Priorität des Prozesses, desto geringer ist die Wahrscheinlichkeit, dass er abgebrochen und recycelt wird.

Oom_adj des normalen App-Prozesses>=0, nur oom_adj des Systemprozesses

Einige Mobiltelefonhersteller haben diese bekannten Apps in ihre eigene Whitelist aufgenommen. Dadurch wird sichergestellt, dass der Prozess zur Verbesserung der Benutzererfahrung nicht unterbrochen wird (z. B. WeChat, QQ und Momo sind alle in Xiaomis enthalten). Whitelist). Wenn sie von der Whitelist entfernt werden, können sie wie gewöhnliche Apps immer noch dem Schicksal entgehen, getötet zu werden. Um so weit wie möglich zu vermeiden, ist es besser, die Optimierungsarbeit ehrlich durchzuführen.

Die grundlegende Lösung, um den Prozess am Leben zu erhalten, liegt also letztendlich in der Leistungsoptimierung. Die Unsterblichkeit des Prozesses ist schließlich eine völlig falsche Behauptung!

8. Kontext erklären

Context ist eine abstrakte Basisklasse. Wenn es als Kontext übersetzt wird, kann es auch als Umgebung verstanden werden, die grundlegende Informationen über die Ausführungsumgebung einiger Programme bereitstellt. Unter Context gibt es zwei Unterklassen. ContextWrapper ist die Kapselungsklasse von Kontextfunktionen, und ContextImpl ist die Implementierungsklasse von Kontextfunktionen. ContextWrapper verfügt über drei direkte Unterklassen: ContextThemeWrapper, Service und Application. Unter diesen ist ContextThemeWrapper eine Paketklasse mit einem Thema, und eine ihrer direkten Unterklassen ist Aktivität, sodass der Kontext von Aktivität, Dienst und Anwendung unterschiedlich ist. Nur Aktivität benötigt ein Thema und Service benötigt kein Thema. Es gibt drei Arten von Kontext: Anwendung, Aktivität und Dienst. Obwohl diese drei Klassen unterschiedliche Rollen spielen, gehören sie alle zu einem Kontexttyp und ihre spezifischen Kontextfunktionen werden von der ContextImpl-Klasse implementiert. Daher sind diese drei Kontexttypen in den meisten Szenarien universell. Es gibt jedoch einige spezielle Szenarien, z. B. das Starten einer Aktivität und das Öffnen eines Dialogs. Aus Sicherheitsgründen lässt Android nicht zu, dass Aktivität oder Dialog aus dem Nichts erscheinen. Der Start einer Aktivität muss auf einer anderen Aktivität basieren, bei der es sich um den dadurch gebildeten Rückgabestapel handelt. Der Dialog muss bei einer Aktivität angezeigt werden (es sei denn, es handelt sich um einen Dialog vom Typ „Systemwarnung“). Daher können wir in diesem Szenario nur den Aktivitätstyp „Kontext“ verwenden, andernfalls tritt ein Fehler auf.

Die von den Methoden getApplicationContext() und getApplication() erhaltenen Objekte sind dasselbe Anwendungsobjekt, die Objekttypen sind jedoch unterschiedlich.

Anzahl der Kontexte = Anzahl der Aktivitäten + Anzahl der Dienste + 1 (1 ist Anwendung)

9. Verstehen Sie die Beziehung zwischen Aktivität, Ansicht und Fenster

Diese Frage ist wirklich verwirrend. Gute Antwort. Hier ist also eine passendere Metapher, um ihre Beziehung zu beschreiben. Aktivität ist wie ein Handwerker (Steuereinheit), Fenster ist wie ein Fenster (das das Modell trägt), Ansicht ist wie ein Fenstergitter (zeigt die Ansicht an), LayoutInflater ist wie eine Schere und die XML-Konfiguration ist wie eine Fenstergitterzeichnung.

1: Wenn eine Aktivität erstellt wird, wird ein Fenster initialisiert, genauer gesagt PhoneWindow.

2: Dieses PhoneWindow hat eine „ViewRoot“ und diese „ViewRoot“ ist eine Ansicht oder ViewGroup, die die anfängliche Stammansicht ist.

3: „ViewRoot“ fügt Ansichten einzeln über die addView-Methode hinzu. Zum Beispiel TextView, Button usw.

4: Die Ereignisüberwachung dieser Ansichten erfolgt durch WindowManagerService, um Nachrichten zu empfangen und die Aktivitätsfunktion zurückzurufen. Zum Beispiel onClickListener, onKeyDown usw.

10. Vier LaunchModes und ihre Einsatzszenarien

Erweiterung hier: der Unterschied zwischen Stack (First In Last Out) und Queue (First In First Out)

Stack und The Unterschied zwischen Warteschlangen:

1. Die Warteschlange ist „First In, First Out“ und der Stapel ist „First In, Last Out“

2. Ein Stapel ist eine lineare Liste, die Einfüge- und Löschvorgänge nur auf ein Ende der Liste beschränkt. Eine Warteschlange ist eine lineare Liste, die Einfügungen auf ein Ende der Tabelle und Löschungen auf das andere Ende beschränkt.

3. Die Geschwindigkeit beim Durchlaufen von Daten ist unterschiedlich

Standardmodus

Dies ist der Standardmodus. Bei jeder Aktivierung der Aktivität wird eine Aktivitätsinstanz erstellt und platziert im Aufgabenstapel. Nutzungsszenarien: die meisten Aktivitäten.

singleTop-Modus

Wenn sich oben im Aufgabenstapel eine Instanz der Aktivität befindet, wird die Instanz wiederverwendet (onNewIntent() der Instanz wird aufgerufen), andernfalls eine neue Die Instanz wird erstellt und an die Spitze des Stapels verschoben. Auch wenn bereits eine Instanz der Aktivität auf dem Stapel vorhanden ist, wird eine neue Instanz erstellt, solange sie sich nicht oben auf dem Stapel befindet. Zu den Nutzungsszenarien gehören Inhaltsseiten von Nachrichten oder Lese-Apps.

SingleTask-Modus

Wenn bereits eine Instanz der Aktivität im Stapel vorhanden ist, wird die Instanz wiederverwendet (onNewIntent() der Instanz wird aufgerufen). Bei der Wiederverwendung wird die Instanz an die Spitze des Stapels zurückgebracht, sodass die darüber liegenden Instanzen aus dem Stapel entfernt werden. Wenn die Instanz nicht auf dem Stapel vorhanden ist, wird eine neue Instanz erstellt und auf dem Stapel platziert. Das Verwendungsszenario ist beispielsweise die Hauptschnittstelle des Browsers. Unabhängig davon, aus wie vielen Anwendungen Sie den Browser starten, wird die Hauptoberfläche nur einmal gestartet. In anderen Fällen wird onNewIntent verwendet und andere Seiten auf der Hauptoberfläche werden gelöscht.

Einzelinstanzmodus

Erstellt eine Instanz der Aktivität in einem neuen Stapel und ermöglicht mehreren Anwendungen, die Aktivitätsinstanz im Stapel gemeinsam zu nutzen. Sobald eine Aktivitätsinstanz dieses Modus bereits in einem Stapel vorhanden ist, verwendet jede Anwendung, die die Aktivität aktiviert, die Instanz im Stapel wieder (onNewIntent() der Instanz wird aufgerufen). Der Effekt ist gleichbedeutend damit, dass mehrere Anwendungen eine Anwendung gemeinsam nutzen. Unabhängig davon, wer die Aktivität aktiviert, gelangen sie zu derselben Anwendung. Verwenden Sie Szenarien wie Alarmerinnerungen, um Alarmerinnerungen von Alarmeinstellungen zu trennen. Verwenden Sie singleInstance nicht für Zwischenseiten, es treten Probleme mit Sprüngen auf, z. B.: A -> B (singleInstance) -> .

11. Zeichenvorgang anzeigen

Benutzerdefinierte Steuerelemente:

1. Diese Art von benutzerdefiniertem Steuerelement erfordert nicht, dass wir es selbst zeichnen, sondern ein neues Steuerelement, das aus nativen Steuerelementen besteht. Wie zum Beispiel die Titelleiste.

2. Erben Sie die ursprüngliche Kontrolle. Diese Art von benutzerdefiniertem Steuerelement kann zusätzlich zu den vom nativen Steuerelement bereitgestellten Methoden einige Methoden hinzufügen. Zum Beispiel abgerundete Ecken und kreisförmige Bilder.

3. Vollständig angepasste Steuerelemente: Der gesamte in dieser Ansicht angezeigte Inhalt wird von uns selbst gezeichnet. Erstellen Sie beispielsweise einen Fortschrittsbalken für Wasserwellen.

Zeichnungsprozess der Ansicht: OnMeasure()——>OnLayout()——>OnDraw()

Schritt eins: OnMeasure(): Messen Sie die Größe der Ansicht. Die Messmethode wird rekursiv von der übergeordneten Ansicht der obersten Ebene zur untergeordneten Ansicht aufgerufen, und die Messmethode ruft OnMeasure zurück.

Schritt 2: OnLayout(): Bestimmen Sie die Ansichtsposition und gestalten Sie die Seite. Der Prozess des rekursiven Aufrufs der view.layout-Methode von der übergeordneten Ansicht der obersten Ebene zur untergeordneten Ansicht bedeutet, dass die übergeordnete Ansicht die untergeordnete Ansicht basierend auf der Layoutgröße und den Layoutparametern, die durch Messen der untergeordneten Ansicht in erhalten werden, an der entsprechenden Position platziert vorherigen Schritt.

Schritt 3: OnDraw(): Zeichnen Sie die Ansicht. ViewRoot erstellt ein Canvas-Objekt und ruft dann OnDraw() auf. Sechs Schritte: ①, den Hintergrund der Ansicht zeichnen; ③, den Inhalt der Ansicht zeichnen ④, wenn nicht, verwenden Sie ihn nicht; 🎜>⑤, Ebene wiederherstellen; ⑥, Bildlaufleiste zeichnen.

12. View- und ViewGroup-Ereignisse sind unterteilt in

1. Es gibt nur zwei Protagonisten bei der Touch-Ereignisverteilung: ViewGroup und View. ViewGroup enthält drei verwandte Ereignisse: onInterceptTouchEvent, DispatchTouchEvent und onTouchEvent. View enthält zwei verwandte Ereignisse: „dispatchTouchEvent“ und „onTouchEvent“. Unter diesen erbt ViewGroup von View.

2. ViewGroup und View bilden eine Baumstruktur und der Wurzelknoten ist eine in der Aktivität enthaltene ViwGroup.

3. Das Touch-Ereignis besteht aus Action_Down, Action_Move und Aciton_UP. In einem vollständigen Touch-Ereignis gibt es nur ein Down und Up und es gibt mehrere Moves, die 0 sein können.

4. Wenn Acitivty das Touch-Ereignis empfängt, durchläuft es die Unteransicht, um das Down-Ereignis zu verteilen. ViewGroup-Durchquerung kann als rekursiv angesehen werden. Der Zweck der Verteilung besteht darin, die Ansicht zu finden, die dieses vollständige Berührungsereignis tatsächlich verarbeitet. Diese Ansicht gibt im onTouchuEvent-Ergebnis „true“ zurück.

5. Wenn eine Unteransicht „true“ zurückgibt, wird die Verteilung des Down-Ereignisses gestoppt und die Unteransicht wird in der ViewGroup aufgezeichnet. Die nachfolgenden Move- und Up-Ereignisse werden direkt von der Unteransicht verarbeitet. Da die Unteransicht in der ViewGroup in der mehrschichtigen ViewGroup-Knotenstruktur gespeichert wird, speichert die ViewGroup der oberen Ebene das ViewGroup-Objekt dort, wo sich die Ansicht befindet, die das Ereignis tatsächlich verarbeitet: Zum Beispiel in der Struktur von ViewGroup0-ViewGroup1 -TextView, TextView gibt true zurück und wird in ViewGroup1 gespeichert. ViewGroup1 gibt ebenfalls true zurück und wird in ViewGroup0 gespeichert. Wenn die Ereignisse „Move“ und „UP“ eintreffen, werden sie zuerst von ViewGroup0 an ViewGroup1 und dann von ViewGroup1 an TextView übergeben.

6. Wenn nicht alle Unteransichten in der ViewGroup das Down-Ereignis erfassen, wird das onTouch-Ereignis der ViewGroup selbst ausgelöst. Der Auslöser besteht darin, die Funktion super.dispatchTouchEvent aufzurufen, bei der es sich um die DispatchTouchEvent-Methode der übergeordneten Klasse View handelt. Wenn nicht alle Unteransichten verarbeitet werden, wird die onTouchEvent-Methode der Aktivität ausgelöst.

7.onInterceptTouchEvent hat zwei Funktionen: 1. Abfangen der Verteilung von Down-Ereignissen. 2. Stoppen Sie die Übermittlung von Up- und Move-Ereignissen an die Zielansicht, sodass die ViewGroup, in der sich die Zielansicht befindet, die Up- und Move-Ereignisse erfasst.

13. Aktivitätsstatus speichern

onSaveInstanceState(Bundle) wird aufgerufen, bevor die Aktivität in den Hintergrundstatus wechselt, d. h. vor der onStop()-Methode und nach der onPause-Methode;

14. Mehrere Animationen in Android

Frame-Animation: Bezieht sich auf die geordnete Wiedergabe, um Animationseffekte zu erzeugen, indem das Bild und die Wiedergabezeit jedes Frames angegeben werden, z. B. der Rhythmusbalken, den Sie anhören möchten.

Tween-Animation: Es bezieht sich auf die Transformation von Grafiken durch eine Reihe von Algorithmen durch Angabe des Anfangszustands, der Änderungszeit und der Methode der Ansicht, um Animationseffekte zu erzeugen. Es gibt hauptsächlich vier Effekte: Alpha, Skalierung, Übersetzen, und Drehen. Hinweis: Der Animationseffekt wird nur in der Ansichtsebene implementiert und ändert nicht wirklich die Eigenschaften der Ansicht, wie z. B. das Verschieben der Liste und das Ändern der Transparenz der Titelleiste.

Attributanimation: Wird nur in Android 3.0 unterstützt. Der Animationseffekt entsteht durch kontinuierliches Ändern der Attribute der Ansicht und ständiges Neuzeichnen. Im Vergleich zur Ansichtsanimation haben sich die Eigenschaften der Ansicht erheblich geändert. Beispielsweise können Sie die Ansicht drehen, vergrößern und verkleinern.

15. Verschiedene Methoden der prozessübergreifenden Kommunikation in Android

Die prozessübergreifende Android-Kommunikation wie Absicht, ContentProvider, Broadcast und Service kann prozessübergreifend kommunizieren.

Absicht: Diese prozessübergreifende Methode ist keine Form des Speicherzugriffs. Sie erfordert die Übergabe eines URI, z. B. einen Anruf.

contentProvider: Dieses Formular nutzt die Datenfreigabe für die Datenfreigabe.

Dienstleistung: Fernwartung, Hilfe

Übertragung

16. AIDL-Verständnis

Erweiterung hier: Kurzbeschreibung von Binder

AIDL: Jeder Prozess verfügt über eine eigene Dalvik-VM-Instanz und einen eigenen unabhängigen Speicher. Jeder Prozess speichert seine eigenen Daten in seinem eigenen Speicher, führt seine eigenen Operationen aus und vervollständigt sein eigenes Leben in seinem eigenen kleinen Raum. Aidl ist wie eine Brücke zwischen zwei Prozessen und ermöglicht die Datenübertragung zwischen den beiden Prozessen. Es gibt viele Optionen für die prozessübergreifende Kommunikation, z. B. BroadcastReceiver, Messenger usw., aber BroadcastReceiver beansprucht mehr Systemressourcen. Prozesskommunikation ist offensichtlich nicht ratsam. Wenn Messenger eine prozessübergreifende Kommunikation durchführt, wird die Anforderungswarteschlange synchron ausgeführt und kann nicht gleichzeitig ausgeführt werden.

Ein einfaches Verständnis des Binde-Mechanismus:

Im Binder-Mechanismus des Android-Systems besteht er aus Client-, Service-, ServiceManager- und Binder-Treibern, darunter Client, Service und Der Service Manager wird im Benutzerbereich ausgeführt, der Binder-Treiber wird im Kernelbereich ausgeführt. Binder ist der Klebstoff, der diese vier Komponenten miteinander verbindet. Die Kernkomponente ist der Binder-Treiber, der zusätzliche Verwaltungsfunktionen bereitstellt, und Client und Service basieren auf der Kommunikation zwischen Binder-Treiber und Service Manager in der Einrichtung. Der Binder-Treiber stellt die Gerätedatei /dev/binder für die Interaktion mit der Benutzersteuerung bereit.

Client, Service und Service Manager kommunizieren mit dem Binder-Treiber über entsprechende Methoden für offene und ioctl-Dateioperationen. Die prozessübergreifende Kommunikation zwischen Client und Service wird indirekt über den Binder-Treiber implementiert. Der Binder Manager ist ein Daemon-Prozess, der den Dienst verwaltet und dem Client die Möglichkeit bietet, die Dienstschnittstelle abzufragen.

17. Das Prinzip des Handlers

Der Hauptthread in Android kann keine zeitaufwändigen Vorgänge ausführen und der Unterthread kann die Benutzeroberfläche nicht aktualisieren. Es gibt also einen Handler, dessen Aufgabe darin besteht, die Kommunikation zwischen Threads zu implementieren.

Handler Im gesamten Prozess gibt es vier Hauptobjekte: Handler, Message, MessageQueue und Looper. Wenn die Anwendung erstellt wird, wird das Handler-Objekt im Hauptthread erstellt.

Wir speichern die zu sendende Nachricht an die MessageQueue, indem wir die sendMessage-Methode aufrufen Das Looper-Objekt ruft weiterhin die Methode loop()

auf, um fortlaufend Nachrichten aus der MessageQueue zu entnehmen und sie dem Handler zur Verarbeitung zu übergeben. Dies ermöglicht die Kommunikation zwischen Threads.

18. Prinzip des Binder-Mechanismus

Im Binder-Mechanismus des Android-Systems besteht er aus Client, Service, ServiceManager und Binder-Treiber, unter denen Client, Service und Service Manager ausgeführt werden user space , der Binder-Treiber läuft im Kernel-Space. Binder ist der Klebstoff, der diese vier Komponenten miteinander verbindet. Die Kernkomponente ist der Binder-Service-Manager, der zusätzliche Verwaltungsfunktionen bereitstellt, und Client und Service basieren auf der Kommunikation zwischen Binder-Treiber und Service-Manager in der Einrichtung. Der Binder-Treiber stellt die Gerätedatei /dev/binder für die Interaktion mit Benutzersteuerelementen bereit. Client, Service und Service Manager kommunizieren über entsprechende Methoden zum Öffnen und Ioctl-Dateivorgang mit dem Binder-Treiber. Die prozessübergreifende Kommunikation zwischen Client und Service wird indirekt über den Binder-Treiber implementiert. Der Binder Manager ist ein Daemon-Prozess, der den Dienst verwaltet und dem Client die Möglichkeit bietet, die Dienstschnittstelle abzufragen.

19. Das Prinzip der Hot Repair

Wir wissen, dass die virtuelle Java-Maschine (JVM) die Klassendatei der Klasse lädt, während die virtuelle Android-Maschine (Dalvik/ART VM) die Dex-Datei lädt der Klasse

und sie alle benötigen ClassLoader, wenn Klassen geladen werden, und es gibt ein

-Array unter BaseDexClassLoader – DexPathList, das zum Speichern von Dex-Dateien verwendet wird BaseDexClassLoader passiert beim Aufrufen der findClass-Methode tatsächlich das Array,

findet die entsprechende Dex-Datei und gibt sie direkt zurück, wenn sie gefunden wird. Die Lösung für die Hot-Reparatur besteht darin, den neuen Dex zur Sammlung hinzuzufügen, und er befindet sich vor dem alten Dex,

, sodass er zuerst herausgenommen und zurückgegeben wird.

20. Android-Speicherlecks und -verwaltung

(1) Der Unterschied zwischen Speicherüberlauf (OOM) und Speicherleck (Objekt kann nicht recycelt werden).

(2) Ursachen für Speicherlecks

(3) Speicherleck-Erkennungstool------>LeakCanary

Speicherüberlauf: Bezieht sich auf Wann Das Programm beansprucht Speicher, es ist nicht genügend Speicherplatz vorhanden, und es wird angezeigt, dass nicht genügend Speicher vorhanden ist. Wenn es beispielsweise eine Ganzzahl anwendet, aber eine Zahl speichert, die nur durch einen Long-Wert gespeichert werden kann, handelt es sich um einen Speicher Überlauf. Laienhaft ausgedrückt bedeutet Speicherüberlauf, dass nicht genügend Speicher vorhanden ist.

Speicherverlust: Speicherverlust bedeutet, dass das Programm, nachdem es Speicher beantragt hat, den beantragten Speicherplatz nicht freigeben kann. Der Schaden eines Speicherverlusts kann ignoriert werden, die Folgen der Anhäufung von Speicherverlusten jedoch Egal wie viel Speicher, früher oder später wird es mit Licht besetzt sein

Ursachen für Speicherverluste:

1. Speicherverlust durch Handler.

Lösung: Deklarieren Sie Handler als statische innere Klasse, damit er keinen Verweis auf die externe Klasse SecondActivity enthält und sein Lebenszyklus nichts mit der externen Klasse zu tun hat.

Wenn Kontext Wird im Handler benötigt, können Sie externe Klassen durch schwache Referenzen referenzieren

2. Speicherverluste durch Singleton-Modus.

Lösung: Context ist ApplicationContext, da der Lebenszyklus von ApplicationContext mit der App übereinstimmt.

3. Speicherlecks, die durch nicht statische innere Klassen verursacht werden Instanzen.

Lösung: Ändern Sie die innere Klasse so, dass sie statisch ist, um Speicherlecks zu vermeiden

4. Speicherlecks, die durch nicht statische anonyme innere Klassen verursacht werden.

Lösung: Setzen Sie die anonyme innere Klasse auf statisch.

5. Speicherlecks durch ungepaarte Nutzung der Registrierung/Aufhebung der Registrierung.

Registrieren Sie Rundfunkempfänger, EventBus usw. und denken Sie daran, die Bindung aufzuheben.

6. Speicherlecks, die dadurch verursacht werden, dass Ressourcenobjekte nicht geschlossen werden.

Wenn diese Ressourcen nicht verwendet werden, denken Sie daran, die entsprechenden Methoden wie close(), destroy(), recycler(), release() usw. aufzurufen, um sie freizugeben.

7. Speicherlecks, die dadurch verursacht werden, dass Sammlungsobjekte nicht rechtzeitig bereinigt werden.

Normalerweise werden einige Objekte in eine Sammlung geladen. Wenn sie nicht verwendet werden, müssen Sie daran denken, die Sammlung rechtzeitig zu bereinigen, damit verwandte Objekte nicht mehr referenziert werden.

21. Wie Fragment mit Fragment und Aktivität kommuniziert

1. Rufen Sie die Methode direkt in einem anderen Fragment auf

2 3. Broadcast verwenden

4.Fragment ruft direkt die öffentliche Methode in Aktivität auf

22. Android-UI-Anpassung

Für Schriftarten verwenden Sie sp, verwenden Sie dp, verwenden Sie mehr match_parent, wrap_content , Gewicht

Bildressourcen, die Auflösung verschiedener Bilder, die im entsprechenden Ordner abgelegt werden, kann durch Prozentsätze ersetzt werden.

23. App-Optimierung

App-Optimierung: (Tool: Hierarchie-Viewer-Analyse-Layout-Tool: TraceView-Testanalyse zeitaufwändig)

App-Startoptimierung

Layout-Optimierung

Reaktionsoptimierung

Speicheroptimierung

Batterienutzungsoptimierung

Netzwerkoptimierung

App-Startoptimierung (für Kaltstart)

Es gibt drei Möglichkeiten, die App zu starten:

Kaltstart: Die App wurde nicht gestartet oder der App-Prozess wurde abgebrochen und der App-Prozess ist nicht im System vorhanden App ist zu diesem Zeitpunkt ein Kaltstart.

Hotstart: Hotstart bedeutet, dass Ihr App-Prozess nur im Hintergrund läuft und das System ihn einfach vom Hintergrund in den Vordergrund bringt und dem Benutzer anzeigt.

Es liegt zwischen Kaltstart und Warmstart. Im Allgemeinen tritt es in den folgenden zwei Situationen auf:

(1) Der Benutzer verlässt die App erneut und startet sie erneut Möglicherweise läuft es immer noch, aber die Aktivität muss neu erstellt werden.

(2) Nachdem der Benutzer die App beendet hat, beendet das System die App möglicherweise aus Speichergründen und sowohl der Prozess als auch die Aktivität müssen neu gestartet werden. Der gespeicherte Instanzstatus der passiven Kill-Sperre kann jedoch in onCreate wiederhergestellt werden.

Optimierung:

OnCreate der Anwendung (insbesondere die SDK-Initialisierung von Drittanbietern) und das Rendern von Aktivitäten auf dem ersten Bildschirm erfordern keine zeitaufwändigen Vorgänge. Wenn ja, können sie platziert werden Untergeordnete Threads oder IntentServices.

Layoutoptimierung

Versuchen Sie, die Verschachtelung nicht zu sehr zu gestalten. Sie können dcf91641426a34cf32ecc36140f28baf, 76deed1c218ccc4d4a17740bf4fefa6a, e7ce6ff74a06bd752b5697fed60b5487 verwenden.

Antwortoptimierung

Das Android-System sendet alle 16 ms ein VSYNC-Signal, um unsere Schnittstelle neu zu zeichnen (Aktivität).

Gründe für Seitenverzögerungen:

(1) Übermäßig komplexes Layout.

(2) Komplexe Vorgänge im UI-Thread

(3) Häufig dort Es gibt zwei Gründe für häufiges GC: 1. Speicherjitter, d. h. eine große Anzahl von Objekten wird in kurzer Zeit erstellt und sofort freigegeben. 2. Das Generieren einer großen Anzahl von Objekten in einem Moment wird den Speicherbereich stark belegen.

Speicheroptimierung: Weitere Informationen finden Sie im Abschnitt zu Speicherlecks und Speicherüberlauf

Optimierung der Batterienutzung (Tools verwenden: Batterystats & Bugreport)

(1) Netzwerkanfragen optimieren

(2) Wenn Sie GPS zur Positionierung verwenden, denken Sie bitte daran, es rechtzeitig auszuschalten

Netzwerkoptimierung (die Auswirkung von Netzwerkverbindungen auf Benutzer: Verkehr, Strom, Benutzerwartezeit) kann vom Tool erkannt werden Netzwerkmonitor neben Logcat unter Android Studio

API-Design: Das API-Design zwischen App und Server sollte die Häufigkeit von Netzwerkanforderungen, den Status von Ressourcen usw. berücksichtigen, damit die App die Geschäftsanforderungen und die Schnittstelle erfüllen kann Anzeige mit weniger Anfragen.

Gzip-Komprimierung: Verwenden Sie Gzip, um Anfragen und Antworten zu komprimieren, wodurch die Menge der übertragenen Daten reduziert wird und dadurch der Verkehrsverbrauch reduziert wird.

Größe des Bildes: Sie können den Server informieren Stellen Sie beim Abrufen des Bildes die erforderliche Breite und Höhe des Bildes ein, damit der Server die entsprechenden Bildbilder bereitstellen kann, um Verschwendung zu vermeiden.

Netzwerk-Caching: Durch ordnungsgemäßes Caching kann unsere Anwendung nicht nur schneller aussehen, sondern auch Vermeiden Sie unnötigen Traffic-Verbrauch.

24. Bildoptimierung

(1) Bearbeiten Sie das Bild selbst. Versuchen Sie, setImageBitmap, setImageResource, BitmapFactory.decodeResource nicht zum Festlegen eines großen Bildes zu verwenden, da diese Methoden nach Abschluss der Dekodierung letztendlich durch createBitmap der Java-Ebene abgeschlossen werden, was mehr Speicher erfordert.

(2) Die Skalierung Das SDK empfiehlt einen exponentiellen Wert von 2. Je größer der Wert, desto größer wird das Bild undeutlich.

(3) Denken Sie daran, die recycle()-Methode nicht verwendeter Bilder aufzurufen

25. HybridApp WebView und JS-Interaktion

Android und JS rufen die Methoden des anderen über WebView auf Tatsächlich ja:

Android ruft JS-Code auf

1. Durch loadUrl() von WebView ist die Verwendung dieser Methode einfacher und bequemer. Allerdings ist die Effizienz relativ gering und es ist schwierig, den Rückgabewert zu ermitteln.

2. Durch die Funktion „evalueJavascript()“ von WebView ist diese Methode hocheffizient, wird jedoch nur von Versionen über 4.4 und nicht von Versionen unter 4.4 unterstützt. Daher empfiehlt es sich, eine Mischung aus beidem zu verwenden.

JS ruft Android-Code auf

1. Die Objektzuordnung erfolgt über addJavascriptInterface() von WebView. Diese Methode ist einfach zu verwenden und ordnet nur Android-Objekte und JS-Objekte zu, weist jedoch relativ große Lücken auf .

Der Grund für die Sicherheitslücke ist: Wenn JS das Android-Objekt erhält, kann es alle Methoden im Android-Objekt aufrufen, einschließlich der Systemklasse (java.lang.Runtime-Klasse), und dadurch beliebigen Code ausführen.

Lösung:

(1) Google schreibt in Android 4.2 vor, dass die aufgerufenen Funktionen mit @JavascriptInterface annotiert werden, um Schwachstellenangriffe zu vermeiden.

(2) Verwenden Sie intercept prompt(), um die Sicherheitslücke vor der Android 4.2-Version zu beheben.

2. Fangen Sie die URL über den Callback der ShouldOverrideUrlLoading()-Methode von WebViewClient ab. Die Vorteile dieser Methode: Es gibt keine Lücken in Methode 1; Nachteile: JS ist kompliziert, den Rückgabewert der Android-Methode zu erhalten. (iOS verwendet hauptsächlich diese Methode)

(1) Android fängt die URL über die Rückrufmethode ShouldOverrideUrlLoading () von WebViewClient ab

(2) Analysiert das Protokoll der URL

( 3) Wenn ein vorab vereinbartes Protokoll erkannt wird, rufen Sie die entsprechende Methode auf

3. Fangen Sie den JS-Dialog „alert()“, „confirm()“ über die Methodenrückrufe „onJsAlert()“, „onJsConfirm()“ und „onJsPrompt()“ ab von WebChromeClient ), prompt()-Nachricht

Vorteile dieser Methode: Es gibt keine Lücken in Methode 1; Nachteile: JS ist kompliziert, den Rückgabewert der Android-Methode zu erhalten.

26. JAVA GC-Prinzip

Die Kernidee des Garbage-Collection-Algorithmus besteht darin, den verfügbaren Speicherplatz der virtuellen Maschine, also der Objekte im Heap-Bereich, zu identifizieren Wenn auf das Objekt verwiesen wird, nennen Sie es ein überlebendes Objekt

. Wenn das Objekt jedoch nicht mehr referenziert wird, handelt es sich um ein Müllobjekt, und der von ihm belegte Platz kann zur Neuzuweisung recycelt werden. Die Wahl des Garbage-Collection-Algorithmus und die angemessene Anpassung der Parameter des Garbage-Collection-Systems wirken sich direkt auf die Systemleistung aus.

27. ANR

Der vollständige Name von ANR lautet „Application Not Responding“, also „Anwendung antwortet nicht“. Ein Dialog wie der oben gezeigte wird auf Systemebene angezeigt.

Ursache:

(1) Auf Benutzereingabeereignisse (z. B. Tastatureingabe, Touchscreen usw.) kann nicht reagiert werden. ) innerhalb von 5 Sekunden.

(2)BroadcastReceiver in 10s Kann nicht innerhalb von 20 Sekunden beendet werden

(3) Dienst kann nicht innerhalb von 20 Sekunden beendet werden (geringe Wahrscheinlichkeit)

Lösung:

(1) Führen Sie keine zeitaufwändigen Vorgänge im Hauptthread aus, sondern sollten Sie sie in einem untergeordneten Thread implementieren. Führen Sie beispielsweise in onCreate() und onResume() so wenige Erstellungsvorgänge wie möglich aus.

(2) Anwendungen sollten zeitaufwändige Vorgänge oder Berechnungen in BroadcastReceiver vermeiden.

(3) Vermeiden Sie es, eine Aktivität im Intent Receiver zu starten, da dadurch ein neuer Bildschirm erstellt wird und dem aktuell vom Benutzer ausgeführten Programm der Fokus entzogen wird.

(4) Der Dienst wird im Hauptthread ausgeführt, daher müssen zeitaufwändige Vorgänge im Dienst in untergeordneten Threads platziert werden.

28. Entwurfsmuster

Erweiterung hier: Double Check muss geschrieben werden.

Einzelfallmodus: unterteilt in Bad-Guy-Stil und Lazy-Guy-Stil

Bösewicht-Stil:

public class Singleton 
{ 
    private static Singleton instance = new Singleton(); 
     
    public static Singleton getInstance() 
    { 
        return instance ; 
    } 
}

Lazy-Guy-Stil:

public class Singleton02 
{ 
    private static Singleton02 instance; 
 
    public static Singleton02 getInstance() 
    { 
        if (instance == null) 
        { 
            synchronized (Singleton02.class) 
            { 
                if (instance == null) 
                { 
                    instance = new Singleton02(); 
                } 
            } 
        } 
        return instance; 
    } 
}

29, RxJava

30. MVP, MVC, MVVM

Erweiterung hier: handgeschriebenes MVP-Beispiel, Unterschied zwischen MVC und MVC, Vorteile von MVP

MVP-Modus, entsprechend Model--Business Logische und Entitätsmodelle, Ansicht – entspricht der Aktivität, ist für das Zeichnen der Ansicht und die Interaktion mit dem Benutzer verantwortlich, Präsentator – ist für die Interaktion zwischen der Ansicht und dem Modell verantwortlich. Der MVP-Modus basiert auf dem MVC-Modus und ist vollständig getrennt Das Modell und die Ansicht, so dass die Kopplung des Projekts in MVC noch geringer ist, entspricht die Aktivität im Projekt dem C--Controller in MVC, und die logische Verarbeitung im Projekt wird in diesem C verarbeitet Zeit, die Interaktion zwischen Ansicht und Modell wird auch gesagt, dass alle logischen Interaktionen und Benutzerinteraktionen in mvc im Controller, also in der Aktivität, platziert werden. Ansicht und Modell können direkt kommunizieren. Das MVP-Modell ist vollständiger getrennt und weist eine klarere Arbeitsteilung auf. Das Modell – Geschäftslogik und Entitätsmodell – ist für die Interaktion mit Benutzern verantwortlich, und Presenter ist für die Vervollständigung der Interaktion zwischen Ansicht und Modell verantwortlich und MVC ermöglicht in MVC die Interaktion von Modell und Ansicht, und in MVP ist es offensichtlich, dass die Interaktion zwischen Modell und Ansicht durch den Präsentator abgeschlossen wird. Ein weiterer Punkt ist, dass die Interaktion zwischen Presenter und View über die Schnittstelle erfolgt

31. Handschriftalgorithmus (muss wissen, wie man Sprudeln auswählt)

32. JNI

(1) Cygwin installieren und herunterladen, Android NDK herunterladen

(2) Design der JNI-Schnittstelle im NDK-Projekt

(3) Verwenden Sie C/C++, um lokale Methoden zu implementieren

(4 ) JNI generiert die Dynamic Link Library .so-Datei

(5) Kopieren Sie die Dynamic Link Library in das Java-Projekt, rufen Sie sie im Java-Projekt auf und führen Sie das Java-Projekt aus

33. RecyclerView und ListView Der Unterschied

RecyclerView kann die Effekte von ListView und GridView sowie den Effekt des Wasserfallflusses vervollständigen. Gleichzeitig können Sie auch die Bildlaufrichtung der Liste festlegen (vertikal oder horizontal);

Für die Wiederverwendung von Ansichten in RecyclerView müssen Entwickler nicht selbst Code schreiben, das System hat ihn bereits für Sie gepackt.

RecyclerView kann eine teilweise Aktualisierung durchführen.

RecyclerView bietet eine API zum Implementieren von Objektanimationseffekten.

In Bezug auf die Leistung:

Wenn Sie Daten häufig aktualisieren und Animationen hinzufügen müssen, hat RecyclerView einen größeren Vorteil.

Wenn es nur als Liste angezeigt wird, ist der Unterschied zwischen den beiden nicht sehr groß.

34. Vergleich von Universal-ImageLoader, Picasso, Fresco und Glide

Fresco ist ein von Facebook eingeführtes Open-Source-Bild-Caching-Tool. Zu seinen Hauptfunktionen gehören: zwei Speicher-Caches plus native Cache-Formung ein dreistufiges Caching,

Vorteile:

1. Bilder werden im anonymen gemeinsamen Speicher des Android-Systems und nicht im Heap-Speicher der virtuellen Maschine gespeichert des Bildes wird auch im lokalen Heap-Speicher gespeichert, sodass die Anwendung mehr Speicher benötigt, kein OOM aufgrund des Ladens des Bildes verursacht und auch die Schnittstellenverzögerung verringert, die durch häufige Aufrufe des Garbage Collectors zum Recyceln von Bitmap verursacht wird, was zu höheren Ergebnissen führt Leistung.

2. Progressives Laden von JPEG-Bildern, unterstützt das Laden von Bildern von verschwommen bis klar.

3. Das Bild kann in der ImageView an jedem beliebigen Mittelpunkt angezeigt werden, nicht nur in der Bildmitte.

4. Die Größenänderung von JPEG-Bildern erfolgt ebenfalls nativ und nicht im Heap-Speicher der virtuellen Maschine, wodurch auch OOM reduziert wird.

5. Sehr gute Unterstützung für die Anzeige von GIF-Bildern.

Nachteile:

1. Das Framework ist groß, was sich auf die Apk-Größe auswirkt

2. Es ist umständlich zu verwenden

Universal-ImageLoader: ( Es wird geschätzt, dass HttpClient durch Google ersetzt wird. Wenn Sie aufgeben, wird der Autor die Pflege dieses Frameworks aufgeben)

Vorteile:

1 Unterstützt die Überwachung des Download-Fortschritts

2 . Das Laden von Bildern kann während des Scrollens der Ansicht über die Schnittstelle „PauseOnScrollListener“ angehalten werden.

3. Diese Bildcaches können alle standardmäßig mit Caching-Algorithmen konfiguriert werden, aber ImageLoader implementiert standardmäßig viele Caching-Algorithmen, wie z. B. „Größte Größe zuerst“, „Am wenigsten verwendet zuerst löschen“ und „Am wenigsten verwendet“. Kürzlich verwendet, First-In-First-Out, Longest-In-First-Out usw.

4. Unterstützt die Definition lokaler Cache-Dateinamen

Picasso-Vorteile

1. Unterstützt die Überwachung der Bild-Cache-Nutzung, einschließlich Cache-Trefferrate, belegter Speichergröße, eingespartem Datenverkehr usw.

2. Unterstützen Sie die Prioritätsverarbeitung. Bevor jede Aufgabe geplant wird, wird eine Aufgabe mit einer höheren Priorität ausgewählt. Dies ist beispielsweise sehr gut geeignet, wenn die Priorität von Banner auf der App-Seite höher ist als die von Icon.

3. Unterstützung der Verzögerung, bis die Bildgrößenberechnung abgeschlossen und geladen ist

4. Unterstützung des Flugmodus, die Anzahl der gleichzeitigen Threads ändert sich je nach Netzwerktyp. Wenn das Telefon in den Flugmodus wechselt oder sich der Netzwerktyp ändert, wird die maximale Parallelitätszahl des Thread-Pools automatisch angepasst. Beispielsweise beträgt die maximale Parallelitätszahl von WLAN 4, 4g ist 3 und 3g ist 2. Hier bestimmt Picasso die maximale Anzahl von Parallelitäten basierend auf dem Netzwerktyp, nicht auf der Anzahl der CPU-Kerne.

5. „Keiner“ lokaler Cache. „Kein“ lokaler Cache bedeutet nicht, dass es keinen lokalen Cache gibt, aber Picasso selbst hat ihn nicht implementiert und ihn zur Implementierung an eine andere Netzwerkbibliothek von Square, okhttp, übergeben. Der Vorteil davon ist, dass das Bild gesteuert werden kann durch Anforderung von Cache-Control und Expired im Response-Header

Vorteile von Glide

1. Es kann nicht nur Bilder zwischenspeichern, sondern auch Mediendateien Cache, es unterstützt GIF, WebP und sogar Video, daher sollte es als Medien-Cache verwendet werden

2. Unterstützt die Prioritätsverarbeitung

3. Konsistent mit dem Aktivitäts-/Fragment-Lebenszyklus Glide unterstützt trimMemory, um für jeden Kontext einen RequestManager zu verwalten. Über FragmentTransaction bleibt es mit dem Aktivitäts-/Fragment-Lebenszyklus konsistent und es steht eine entsprechende trimMemory-Schnittstellenimplementierung zum Aufrufen zur Verfügung.

4. Unterstützt okhttp und Volley. Glide erhält Daten standardmäßig über okhttp oder Volley. Tatsächlich unterstützt der Speichercache von Glide ein aktives Design Cache, es ist nicht wie die allgemeine Implementierung von get. Verwenden Sie „Remove“ und fügen Sie diese zwischengespeicherten Daten dann in eine ActiveResources-Karte ein, deren Wert eine weiche Referenz ist, und zählen Sie die Anzahl der Referenzen. Nachdem das Bild geladen wurde, wird es beurteilt. Wenn der Referenzzähler leer ist, wird das kleinere Bild recycelt und Glide speichert das kleinere Bild zwischen. URL, Ansichtsbreite, Ansichtshöhe, Bildschirmauflösung usw. werden als gemeinsame Schlüssel verwendet, um das verarbeitete Bild im Speichercache zwischenzuspeichern Bild zum Speichern der Größe im Einklang mit dem Aktivitäts-/Fragmentlebenszyklus wird standardmäßig für Bilder RGB_565 anstelle von ARGB_888 unterstützt, obwohl die Auflösung schlechter ist, ist das Bild kleiner und kann auch auf ARGB_888 konfiguriert werden

6. Glide kann den URL-Ablauf durch Signatur oder ohne Verwendung des lokalen Caches unterstützen

42. Vergleich von Xutils, OKhttp, Volley, Retrofit

Xutils ist ein sehr umfassendes Framework, das Netzwerkanfragen und Bilder ausführen kann Laden, Datenspeicherung und Annotation von Ansichten Die Verwendung dieses Frameworks ist sehr praktisch, weist jedoch auch Mängel auf. Es ist auch sehr offensichtlich, dass die Verwendung dieses Projekts zu einer starken Abhängigkeit des Projekts von diesem Framework führt Dieser Rahmen wird einen großen Einfluss auf das Projekt haben. ,

OKhttp: In der Android-Entwicklung können Sie die vorgefertigte API direkt verwenden, um Netzwerkanfragen zu stellen. Verwenden Sie zum Betrieb einfach HttpClient und HttpUrlConnection. Für Java- und Android-Programme kapselt okhttp eine leistungsstarke HTTP-Anforderungsbibliothek, die Synchronisation und Asynchronität unterstützt. Darüber hinaus kapselt okhttp auch den Thread-Pool, die Datenkonvertierung, die Parameterverwendung, die Fehlerbehandlung usw. Die API ist bequemer zu verwenden. Wenn wir es jedoch im Projekt verwenden, müssen wir noch selbst eine Kapselungsschicht erstellen, damit es reibungsloser verwendet werden kann.

Volley ist eine kleine und elegante asynchrone Anforderungsbibliothek, die offiziell von Google veröffentlicht wurde. Das Framework ist hoch skalierbar und unterstützt HttpClient, HttpUrlConnection und sogar OkHttp. Wenn Sie möchten, können Sie dies auch tun. Es ist nicht einmal erforderlich, ein Bildlade-Framework zu verwenden. Diese Funktion ist jedoch nicht so leistungsstark wie einige spezielle Bildlade-Frameworks. Sie kann für einfache Anforderungen verwendet werden, komplexere Anforderungen erfordern jedoch immer noch die Verwendung eines speziellen Bildlade-Frameworks. Volley weist auch Mängel auf, z. B. unterstützt es Post-Big-Data nicht und eignet sich daher nicht zum Hochladen von Dateien. Die ursprüngliche Absicht des Volley-Designs selbst besteht jedoch darin, häufige Netzwerkanforderungen mit kleinen Datenmengen zu erfüllen.

Retrofit: Retrofit ist ein RESTful-Netzwerkanforderungsframework, das standardmäßig auf der OkHttp-Kapselung basiert und von Square erstellt wird. RESTful ist ein derzeit beliebter API-Designstil und kein Standard. Man kann sagen, dass die Kapselung von Retrofit eine Reihe von Entwurfsmustern umfasst, die direkt über Anmerkungen konfiguriert werden können. Standardmäßig können verschiedene HTTP-Clients verwendet werden, um Daten zu serialisieren. Gleichzeitig wird Retrofit + OkHttp + RxJava + Dagger2 verwendet, um RxJava zu unterstützen. Man kann sagen, dass es sich derzeit um ein relativ trendiges Framework handelt, das jedoch einen relativ hohen Schwellenwert erfordert.

Volley VS OkHttp

Der Vorteil von Volley besteht darin, dass es besser gekapselt ist. Bei der Verwendung von OkHttp müssen Sie jedoch über genügend Fähigkeiten verfügen, um erneut zu kapseln. Der Vorteil von OkHttp ist eine höhere Leistung. Da OkHttp auf NIO und Okio basiert, ist die Leistung schneller als bei Volley. IO und NIO sind beides Konzepte in Java. Die erste Möglichkeit besteht darin, dass das Programm wartet, bis die Daten gelesen werden, bevor es den Vorgang fortsetzt. Dies wird auch als blockierende IO bezeichnet dass Sie Ihre Daten lesen, das Programm weiter ausführt und Sie mich benachrichtigen, nachdem die Daten verarbeitet wurden, und dann den Rückruf bearbeiten. Die zweite Methode ist NIO, die nicht blockiert, daher hat NIO natürlich eine bessere Leistung als IO. Okio ist eine von Square erstellte Bibliothek, die auf IO und NIO basiert und Datenströme einfacher und effizienter verarbeitet. Wenn Sie Volley mit OkHttp vergleichen, neigen Sie theoretisch eher dazu, Volley zu verwenden, da Volley auch die interne Verwendung von OkHttp unterstützt, sodass der Leistungsvorteil von OkHttp wegfällt und Volley selbst einfacher zu verwenden ist und eine bessere Skalierbarkeit aufweist.

OkHttp VS Retrofit

Es besteht kein Zweifel, dass Retrofit standardmäßig ein Paket ist, das auf OkHttp basiert. In dieser Hinsicht gibt es keinen Vergleich, und Retrofit wird definitiv bevorzugt.

Volley VS Retrofit

Beide Bibliotheken sind gut gekapselt, aber Retrofit ist gründlicher entkoppelt, insbesondere wenn Retrofit 2.0 herauskommt, repariert Jake die unvernünftigen Teile des vorherigen 1.0-Designs , die Verantwortlichkeiten sind stärker unterteilt und Retrofit verwendet standardmäßig OkHttp, was hinsichtlich der Leistung einen Vorteil gegenüber Volley hat. Wenn Ihr Projekt außerdem RxJava verwendet, sollten Sie Retrofit verwenden. Daher bietet Retrofit im Vergleich zu diesen beiden Bibliotheken mehr Vorteile. Wenn Sie beide Frameworks beherrschen, sollten Sie zuerst Retrofit verwenden. Der Schwellenwert für Retrofit ist jedoch etwas höher als der von Volley. Es erfordert einige Anstrengung, seine Prinzipien und verschiedenen Verwendungsmöglichkeiten zu verstehen. Wenn Sie Volley vollständig verstehen möchten, wird empfohlen, Volley in kommerziellen Projekten zu verwenden.

Java

1. Der Unterschied zwischen Sleep und Wait in Threads

(1) Diese beiden Methoden stammen aus verschiedenen Klassen, Sleep kommt von Thread und Wait kommt von Object ;

(2) Die Schlafmethode gibt die Sperre nicht frei, aber die Wartemethode gibt die Sperre frei.

(3) Warten, benachrichtigen, benachrichtigenAlle können nur in Synchronisationssteuerungsmethoden oder Synchronisationssteuerungsblöcken verwendet werden, während Sleep überall verwendet werden kann.

2. Was ist der Unterschied zwischen den Methoden start() und run() in Thread

Die Methode start() wird zum Starten eines neu erstellten Threads und start() intern verwendet? ruft die run()-Methode auf, was sich vom direkten Aufruf der run()-Methode unterscheidet. Wenn die run()-Methode direkt aufgerufen wird, unterscheidet sich

nicht von der normalen Methode.

3. So verwenden Sie die Schlüsselwörter final und static.

final:

1. Die finale Variable ist eine Konstante und kann nur einmal einen Wert zuweisen.

2. Die letzte Methode kann nicht von Unterklassen überschrieben werden.

3. Abschlussklassen können nicht vererbt werden.

statisch:

1. Statische Variablen: Es gibt nur eine Kopie statischer Variablen im Speicher (Speichereinsparung). Die JVM weist statischen Speicher nur einmal zu,

beim Laden Eine Klasse Die Speicherzuweisung statischer Variablen wird dabei abgeschlossen und kann direkt über den Klassennamen aufgerufen werden (praktisch). Natürlich kann auch über Objekte darauf zugegriffen werden (dies wird jedoch nicht empfohlen).

2. Statischer Codeblock

Der statische Codeblock wird automatisch während der Initialisierung ausgeführt, wenn die Klasse geladen wird.

3. Statische Methode

Die statische Methode kann direkt über den Klassennamen aufgerufen werden, und jede Instanz kann ebenfalls aufgerufen werden, sodass die Schlüsselwörter this und super in der statischen Methode nicht verwendet werden können.

Sie können nicht direkt auf Instanzvariablen und Instanzmethoden der Klasse zugreifen, zu der Sie gehören (d. h. auf Mitgliedsvariablen und Mitgliedsmethoden ohne Statik), Sie können nur auf statische Mitgliedsvariablen und Mitgliedsmethoden der Klasse zugreifen, zu der Sie gehören.

Unterschiede zwischen String, StringBuffer und StringBuilder

1. Die Ausführungsgeschwindigkeit der drei: StringBuilder > wird beim Zusammenfügen eines neuen Objekts neu erstellt.

2. StringBuffer ist Thread-sicher und StringBuilder ist Thread-unsicher. (Weil StringBuffer einen Puffer hat)

5. Der Unterschied zwischen Überladen und Umschreiben in Java:

1. Überladen: Es kann mehrere Methoden mit demselben Namen in einer Klasse geben, aber die Parameter Art und Anzahl sind unterschiedlich. Das ist eine Überlastung.

2. Umschreiben: Wenn eine Unterklasse die übergeordnete Klasse erbt, kann die Unterklasse die Methoden in der übergeordneten Klasse implementieren, sodass die neue Methode die alte Methode der übergeordneten Klasse überschreibt.

6. Unterschiede zwischen Http und https

Erweiterung hier: Implementierungsprinzip von https

1. Das https-Protokoll erfordert in der Regel weniger Kostenlose Zertifikate, daher ist ein gewisser Kostenaufwand erforderlich.

2. http ist ein Hypertext-Übertragungsprotokoll und Informationen werden im Klartext übertragen, während https ein sicheres SSL-verschlüsseltes Übertragungsprotokoll ist.

3. http und https verwenden völlig unterschiedliche Verbindungsmethoden und verwenden unterschiedliche Ports. Ersteres ist 80 und letzteres ist 443.

4. Die HTTP-Verbindung ist sehr einfach und zustandslos; das HTTPS-Protokoll ist ein Netzwerkprotokoll, das auf dem SSL+HTTP-Protokoll basiert und eine verschlüsselte Übertragung und Identitätsauthentifizierung durchführen kann und sicherer als das HTTP-Protokoll ist.

https-Implementierungsprinzip:

(1) Der Kunde greift über die https-URL auf den Webserver zu und benötigt den Aufbau einer SSL-Verbindung mit dem Webserver.

(2) Nach Erhalt der Anfrage des Clients übermittelt der Webserver eine Kopie der Zertifikatsinformationen der Website (das Zertifikat enthält den öffentlichen Schlüssel) an den Client.

(3) Der Browser des Clients und der Webserver beginnen mit der Aushandlung der Sicherheitsstufe der SSL-Verbindung, also der Stufe der Informationsverschlüsselung.

(4) Der Browser des Clients erstellt einen Sitzungsschlüssel basierend auf der von beiden Parteien vereinbarten Sicherheitsstufe und verwendet dann den öffentlichen Schlüssel der Website, um den Sitzungsschlüssel zu verschlüsseln und an die Website zu übertragen.

(5) Der Webserver verwendet seinen eigenen privaten Schlüssel, um den Sitzungsschlüssel zu entschlüsseln.

(6) Der Webserver verwendet den Sitzungsschlüssel, um die Kommunikation mit dem Client zu verschlüsseln.

7. Auf welcher Ebene im TCP/IP-Modell befindet sich HTTP? Warum ist HTTP ein zuverlässiges Datenübertragungsprotokoll?

Tcp/IP-Fünfschichtmodell:

Von unten nach oben: physikalische Schicht->Datenverbindungsschicht->Netzwerkschicht->Transportschicht->Anwendungsschicht

Unter diesen befindet sich TCP/IP auf der Netzwerkebene im Modell, und ICMP (Network Control Message Protocol) befindet sich ebenfalls auf derselben Ebene. http befindet sich im Modell in der Anwendungsschicht

Da TCP/IP ein zuverlässiges verbindungsorientiertes Protokoll ist und http auf der Transportschicht auf dem TCP/IP-Protokoll basiert, ist http eine zuverlässige Datenübertragung Protokoll.

8. Merkmale von HTTP-Links

Das wichtigste Merkmal von HTTP-Verbindungen ist, dass jede vom Client gesendete Anfrage eine Antwort zurücksendet. Nachdem die Anfrage abgeschlossen ist, wird die Verbindung hergestellt wird aktiv freigegeben.

Der Vorgang vom Verbindungsaufbau bis zum Schließen der Verbindung wird als „eine Verbindung“ bezeichnet.

9. Der Unterschied zwischen TCP und UDP

TCP ist verbindungsorientiert. Da die TCP-Verbindung drei Handshakes erfordert, kann sie das Risiko minimieren und die Zuverlässigkeit der Verbindung gewährleisten.

UDP ist nicht verbindungsorientiert. UDP muss keine Verbindung mit dem Objekt herstellen, bevor es eine Verbindung herstellt. Es wird kein Bestätigungssignal gesendet. UDP ist also unzuverlässig.

Da UDP die Verbindung nicht bestätigen muss, hat UDP weniger Overhead und eine höhere Übertragungsrate, sodass der Echtzeitbetrieb besser ist.

10. Schritte für Socket zum Herstellen einer Netzwerkverbindung

Der Aufbau einer Socket-Verbindung erfordert mindestens ein Socket-Paar, von denen einer mit dem Client ausgeführt wird – ClientSocket, und einer mit dem server--ServiceSocket

1. Serverüberwachung: Der serverseitige Socket findet den spezifischen Client-Socket nicht, sondern wartet auf die Verbindung, überwacht den Netzwerkstatus in Echtzeit und wartet auf den Verbindungsanfrage des Clients.

2. Client-Anfrage: Bezieht sich auf den Socket des Clients, der eine Verbindungsanforderung stellt, und das zu verbindende Ziel ist der Socket des Servers. Hinweis: Der Socket des Clients muss den Socket des Servers beschreiben, mit dem er eine Verbindung herstellen möchte.

gibt die Adresse und Portnummer des Server-Sockets an und stellt dann genau wie der serverseitige Socket eine Verbindungsanfrage.

3. Verbindungsbestätigung: Wenn der serverseitige Socket die Verbindungsanforderung des Client-Sockets überwacht, antwortet er auf die Anfrage des Client-Sockets, richtet einen neuen Thread ein und verbindet den serverseitigen Socket. Die Beschreibung des Wortes

wird an den Kunden gesendet. Sobald der Kunde diese Beschreibung bestätigt, stellen die beiden Parteien offiziell eine Verbindung her. Der Server-Socket befindet sich weiterhin im Überwachungsstatus und empfängt weiterhin Verbindungsanfragen von anderen Client-Sockets.

11. Tcp/IP-Drei-Wege-Handshake, vier Wellen

Das obige ist der detaillierte Inhalt vonFragen im Vorstellungsgespräch für Fortgeschrittene und Fortgeschrittene mit Android (mit Antworten). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen