[JAVA] Programmier-Memorandum-Prozess-Thread aus 51 Jahre alter Handler-Referenz

Für den persönlichen Gebrauch

Prozesse und Threads

https://developer.android.com/guide/components/processes-and-threads?hl=JA (2019/8/24)

Multithread-Zusammenfassung finden Sie hier

Prozess


Beziehung zwischen Komponenten, Prozessen und Threads


Manifest-Einstellungen

Wenn Sie den Prozess verwalten möchten, zu dem eine bestimmte Komponente gehört, geben Sie ihn in der Manifestdatei an.

Manifest-Einträge für jeden Typ von Komponentenelement (\ <Aktivität> / \ / \ <Empfänger> / \ ) </ strong> </ font> Unterstützt das Attribut android: process </ strong>, das den Prozess angibt, der die Komponente ausführt.

Abhängig von den Einstellungen für ** android: process ** kann jede Komponente in einem eigenen Prozess ausgeführt werden, einige Komponenten können denselben Prozess gemeinsam nutzen oder verschiedene Prozesse können verwendet werden. Sie können auch Komponenten verschiedener Anwendungen im selben Prozess ausführen lassen (die Apps müssen dieselbe Linux-Benutzer-ID verwenden und mit demselben Zertifikat signiert sein).

Das Element ** \ ** unterstützt auch "android: process" und legt Standardwerte fest, die für alle Komponenten gelten.

Das Android-System kann Prozesse herunterfahren und Anwendungskomponenten zerstören. Bei der Entscheidung über den zu verwerfenden Prozess ermittelt das System die Kandidaten anhand der relativen Nachfrage. Später erkläre ich die Regeln, die den Prozess des Verwerfens bestimmen.


Prozessbedeutungshierarchie

Basierend auf den im Prozess ausgeführten Komponenten und dem Status der Komponenten positioniert das Android-System jeden Prozess in einer "Prioritätshierarchie" und versucht, ihn aus weniger wichtigen Prozessen zu entfernen und Systemressourcen wiederherzustellen.

Prozessbedeutungshierarchie 5 Ebenen

  1. Vordergrundprozess
  2. Sichtbarer Prozess
  3. Serviceprozess
  4. Hintergrundprozess
  5. Prozess leeren
1. Vordergrundprozess
  • Wird von der benutzergesteuerten Aktivität </ font> gehostet ( Die onResume () -Methode </ font> der Aktivität wurde aufgerufen).
  • An die vom Benutzer ausgeführte Aktivität gebunden (gehostet von Service </ font>) --Hosted Dienst </ font> wird im Vordergrund ausgeführt (Dienst namens startForeground () </ font>)
  • onCreate (), onStart (), onDestroy () </ font> führt einen Lebenszyklus-Rückruf durch Service </ font> Ist der Gastgeber von> -Hostete den BroadcastReceiver </ font>, auf dem die onReceive () </ font> -Methode ausgeführt wird

Wenn Ihnen der Speicher oder die Ressourcen ausgehen, müssen Sie den Vordergrundprozess beenden.

2. Sichtbarer Prozess

Ein Prozess, der keine Vordergrundkomponente ist, aber den Inhalt des Benachrichtigungsbereichs für den Benutzer beeinflussen kann. Es wird als sichtbarer Prozess angesehen, wenn:

  • Obwohl nicht im Vordergrund, ist es der Host der Aktivität </ font>, die dem Benutzer angezeigt wird ( onPause () </ font> > Die Methode wurde aufgerufen).

  • Sie hosten einen Service </ font>, der an eine sichtbare (oder Vordergrund-) Aktivität gebunden ist.

Sichtbare Prozesse sind von großer Bedeutung und werden nur beendet, wenn der Vordergrundprozess weiter ausgeführt werden muss.

3. Serviceprozess

Der Prozess zum Ausführen eines Dienstes, der mit der Methode startService () </ font> gestartet wurde und nicht in die beiden oben genannten Kategorien fällt. Zusammen mit allen Vordergrund- und sichtbaren Prozessen sind sie nur dann Kandidaten für das Töten, wenn nicht genügend Speicher vorhanden ist, um sie fortzusetzen.

4. Hintergrundprozess

Ein Prozess, der eine Aktivität enthält, die für den Benutzer nicht sichtbar ist (die Methode onStop () </ font> wurde aufgerufen). Es kann jederzeit beendet werden, um den Speicher wiederherzustellen. Hintergrunddienste werden in der LRU-Liste (Least Recent Used) verwaltet und vom ältesten Vorgang beendet.

Wenn die Aktivität die Lebenszyklusmethode genau implementiert und ihren aktuellen Status beibehält, wird der visuelle Status wiederhergestellt, wenn sie fortgesetzt wird, auch wenn sie beendet wird.

5. Prozess leeren

Ein Prozess ohne aktive Anwendungskomponenten. Dieser Prozess wird zum Zwischenspeichern des Prozesses beibehalten und startet schnell die nächste Komponente. Dieser Prozess wird häufig abgebrochen.


Positionieren Sie den Prozess für Komponenten mit mehreren Wichtigkeiten im wichtigsten Rang. Außerdem kann ein Prozess, der für einen anderen Prozess ausgeführt wird, nicht unter dem abhängigen / gebundenen Prozess positioniert werden (wenn er darunter positioniert ist, kann er nicht ausgeführt werden, wenn der abhängige Prozess zerstört wird. ).

Dienste sind wichtiger als der Hintergrund, und für Aktivitäten mit langer Laufzeit (insbesondere wenn der Prozess länger als die Aktivität dauert) sollte der Prozess den Dienst verwenden, anstatt einen Arbeitsthread zu erstellen. Wenn Sie beispielsweise ein Bild ins Web hochladen, verwendet die Aktivität einen Dienst, mit dem der Benutzer beim Verlassen der Aktivität im Hintergrund weiterarbeiten kann. Sogar Rundfunkempfänger sollten Dienste nutzen, anstatt sie über einen längeren Zeitraum von Threads verarbeiten zu lassen.

Faden

Wenn die Anwendung gestartet wird, erstellt das System einen Hauptthread zum Ausführen der Anwendung. Der Haupt-Thread ist sehr wichtig, um für das Senden von Ereignissen (einschließlich Zeichenereignissen) an die entsprechenden UI-Widgets verantwortlich zu sein.

Der Hauptthread ermöglicht der App auch die Interaktion mit Komponenten im Android UI Toolkit (Komponenten im Paket android.widget / android.view </ font>). Daher wird der Hauptthread auch als UI-Thread bezeichnet (in einigen besonderen Fällen ist der Hauptthread nicht der UI-Thread).

Für jede Instanz der Komponente wird kein separater Thread erstellt. Alle Komponenten, die im selben Prozess ausgeführt werden, werden im UI-Thread instanziiert, und das System ruft die vom UI-Thread gesendeten Komponenten auf. Methoden, die auf Systemrückrufe reagieren, werden immer im UI-Thread des Prozesses ausgeführt.

(Beispiel: Wenn der Benutzer eine Schaltfläche auf dem Bildschirm berührt, sendet der UI-Thread der App ein Berührungsereignis an das Widget, das Widget legt den Berührungsstatus fest und der UI-Thread sendet eine Ungültigkeitsanforderung an die Ereigniswarteschlange. Empfängt eine Anfrage aus der Warteschlange und benachrichtigt das Widget über das Zeichnen.

Wenn alles in einem UI-Thread erledigt ist, kann das Ausführen zeitaufwändiger Vorgänge die gesamte UI blockieren. Außerdem ist das Android UI Toolkit nicht threadsicher, sodass Sie nicht über Worker-Threads mit der Benutzeroberfläche interagieren können. Alle Vorgänge müssen über den UI-Thread ausgeführt werden. Daher gibt es zwei Regeln für das Android-Single-Thread-Modell.

Single-Thread-Modellregel

1. Blockieren Sie keine UI-Threads 2. Greifen Sie nur von dem UI-Thread </ strong> auf das Android-UI-Toolkit zu Zugriffsmethoden werden nicht vom UI-Thread bereitgestellt. ( View kann nur von dem Thread aus bedient werden, der die View </ font> </ strong> erstellt hat.)


Arbeitsthread

Der Arbeitsthread ist ein Thread ohne Benutzeroberfläche und führt die empfangene Verarbeitungsanforderung aus (auch als backgroundThread bezeichnet). Der Arbeitsthread verhält sich so, als würde er warten, auch wenn keine Verarbeitungsanforderung vorliegt, und führt ihn aus, wenn er die Verarbeitungsanforderung empfängt. Abhängig vom Verarbeitungsinhalt können mehrere Arbeitsthreads vorhanden sein, und der Speicherort kann als Thread-Pool bezeichnet werden. </ font>

Das Single-Threaded-Modell sollte keine UI-Threads blockieren, um die Reaktionsfähigkeit der UI der Anwendung zu gewährleisten. Vorgänge, die nicht sofort ausgeführt werden müssen, werden in einem separaten Thread (Arbeitsthread (Hintergrundthread)) ausgeführt.

<Referenz: Regelverletzungscode </ font> >>

python


public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            Bitmap b = loadImageFromNetwork("http://example.com/image.png ");
            mImageView.setImageBitmap(b);
        }
    }).start();
}

Der Versuch, ImageView </ font> im Worker-Thread anstelle des UI-Threads zu ändern, verstößt gegen Regel 2 (auf das Android UI Toolkit wird nur über den UI-Thread zugegriffen).

Zugriffsmethode von einem anderen als dem UI-Thread
  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable,long)

<Referenz: Geänderter Code von View.post (ausführbar) </ font> >> Implementieren Sie View.post (Runnable), um den Thread sicher zu machen

python


public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            final Bitmap bitmap =
                    loadImageFromNetwork("http://example.com/image.png ");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}

Netzwerkoperationen werden in einem separaten Thread (loadImageFromNetwork ()) ausgeführt. ImageView wird über den UI-Thread (mImageView.post (new Runnable () {})) betrieben.

Die Methode zur Verwendung von View.post zum Betreiben einer Ansicht über einen UI-Thread ist schwierig zu pflegen, da der Vorgang kompliziert wird. Um komplexe Interaktionen mit Worker-Threads zu verarbeiten, können Sie Handler in Worker-Threads verwenden, um von UI-Threads übermittelte Nachrichten zu verarbeiten. Die empfohlene Methode besteht jedoch darin, die AsyncTask-Klasse zu erweitern. Vereinfacht die Ausführung von Worker-Thread-Aufgaben, die mit der Benutzeroberfläche interagieren.

Verwendung von AsyncTask

AsyncTask führt eine asynchrone Verarbeitung durch. Sie müssen den Thread oder Handler nicht selbst behandeln, er blockiert den Betrieb des Worker-Threads und liefert das Ergebnis an den UI-Thread.

Um AsyncTask zu verwenden, unterordnen Sie AsyncTask </ font> und führen Sie es in einem Pool von Hintergrundthreads aus. doInBackground () </ font> Rückruf Implementieren Sie die Methode.

Implementieren Sie onPostExecute () </ font>, um das Ergebnis in der Benutzeroberfläche wiederzugeben. onPostExecute () </ font> liefert das Ergebnis von doInBackground () </ font> an die Benutzeroberfläche und aktualisiert den UI-Thread, also die Benutzeroberfläche Kann sicher aktualisiert werden. Der UI-Thread ruft execute () </ font> auf, um die Aufgabe auszuführen.

<Referenz: Schreiben Sie den obigen Code mit AsycnTask neu>

public void onClick(View v){
   new DownloadImageTask().execute("http://example.com/image.png ");
}

private class DownloadImageTask extends AsyncTask<String,Void,Bitmap>{
   //Das System ruft die folgende Methode auf, um sie im Arbeitsthread zu verarbeiten:
   //   AsyncTask.execue()Liefern Sie die von der Methode übergebenen Parameter
   protected Bitmap doInBackground(String... urls){
      return loadImageFromNetwork(urls[0]);
   }

   //Das System ruft die folgende Methode zur Verarbeitung im UI-Thread auf
   //   doInBackground()Liefern Sie das Ergebnis an die Methode
   protected void onPostExecute(Bitmap result){
      mImageView.setImageBitmap(result);
   }
}

Die Arbeit des Worker-Threads und die Arbeit des UI-Threads sind getrennt, sodass die UI sicher und der Code einfach ist.

So funktioniert AsyncTask

--Generics kann verwendet werden, um den Parametertyp, den Fortschrittswert und den Endwert der Aufgabe anzugeben

  • Die Methode doInBackground () </ font> wird automatisch im Arbeitsthread ausgeführt
  • onPreExecute (), onPostExecute (), onProgressUpdate () </ font> werden alle im UI-Thread aufgerufen -Der Rückgabewert von doInBackground () </ font> wird an onPostExecute () </ font> gesendet
  • PublishProgress () </ font> kann mit doInBacktround () </ font> und im UI-Thread aufgerufen werden. Sie können onProgressUpdate () </ font> ausführen
  • Sie können eine Aufgabe jederzeit von einem beliebigen Thread aus abbrechen
COUSION: Probleme, die bei der Verwendung von Arbeitsthreads auftreten können
Änderungen an den Laufzeiteinstellungen, z. B. beim Drehen des Bildschirms, können dazu führen, dass die Aktivität unerwartet neu gestartet wird und der Arbeitsthread zerstört wird. Im folgenden Beispiel-Quellcode der App erfahren Sie, wie Sie die Aufgabe während des Neustarts beibehalten und die Aufgabe ordnungsgemäß abbrechen, wenn die Aktivität zerstört wird.> Https://code.google.com/archive/p/ Regale /
Weitere Informationen zu AsyncTask> https://developer.android.com/reference/android/os/AsyncTask.html?hl=JA

Thread-sichere Methode

Wenn die implementierte Methode von mehreren Threads aufgerufen wird, erstellen Sie die Methode so, dass sie threadsicher ist.

Fern aufgerufene Methoden, z. B. von primär gebundenen Diensten, können von mehreren Threads aus aufgerufen werden. Beim Aufruf von mehreren Threads lauten die Threads, die die remote aufgerufene Methode ausführen, wie folgt.

  • Ein in IBinder </ font> implementierter Methodenaufruf wurde im selben Prozess ausgeführt, in dem IBinder </ font> ausgeführt wird. In diesem Fall ist der Thread, der die Methode ausführt, der aufrufende Thread.
  • Wenn von einem anderen Prozess aufgerufen, wird der Thread, der die Methode ausführt, aus dem Thread-Pool ausgewählt, den das System im selben Prozess wie IBinder </ font> aufbewahrt. (Nicht im UI-Thread ausgeführt).

Beispielsweise wird die onBind () </ font> -Methode des Dienstes von einem UI-Thread im Prozess des Dienstes aufgerufen, während onBind () Die in dem von </ font> zurückgegebenen Objekt implementierten Methoden (z. B. die Unterklasse, die die RPC-Methode implementiert) werden von Threads im Thread-Pool aufgerufen. Da der Dienst mehrere Clients haben kann, können mehrere Thread-Pools gleichzeitig dieselbe IBinder-Methode </ font> ausführen. Daher muss die IBinder-Methode implementiert werden, um threadsicher zu sein. ..

RPC-Methode: Die Methode wird lokal aufgerufen, remote ausgeführt (in einem anderen Prozess) und das Ergebnis an den Aufrufer zurückgegeben. </ font>

Ebenso können Inhaltsanbieter Datenanforderungen empfangen, die von anderen Prozessen gesendet wurden. Die Klassen ContentResolver </ font> und ContentProvider </ font> verdecken die Verwaltung der Kommunikation zwischen Prozessen. Die ContentProvider </ font> -Methode ( query (), insert (), delete (), updater (), getType) antwortet jedoch auf diese Anforderungen. () </ Font>) wird als Thread-Pool im Prozess des Inhaltsanbieters und nicht als UI-Thread des Prozesses bezeichnet. Diese Methoden können von mehreren Methoden gleichzeitig aufgerufen werden und müssen implementiert werden, um threadsicher zu sein.

Gewindesicher

Steuern (Synchronisieren), Arbitrieren oder Steuern anderer Threads, während ein Thread ausgeführt wird, um Thread-Konflikte zu vermeiden (Beziehungen, in denen mehrere Threads gleichzeitig auf dieselbe Klasse, Methode oder Variable zugreifen und Daten zerstören). Exklusive Kontrolle) und machen Sie die Klasse oder Methode auch dann sicher, wenn der gleichzeitige Zugriff von mehreren Threads aus erfolgt.

Interprozesskommunikation (IPC)

Android verfügt über einen Mechanismus für die Kommunikation zwischen Prozessen mithilfe eines Remote Procedure Call (RPC), bei dem eine Methode von einer Aktivität oder einer anderen Anwendungskomponente aufgerufen, dann remote ausgeführt wird (ein anderer Prozess) und das Ergebnis aufgerufen wird. Kehrt zu zurück. Da das System für die Verarbeitung der Kommunikation zwischen Prozessen verantwortlich ist, muss der Entwickler nur die RPC-Programmierschnittstelle definieren und implementieren. Für die IPC-Ausführung muss die App mit bindService () </ font> an den Dienst gebunden sein. Weitere Informationen> https://developer.android.com/guide/components/services.html?hl=JA

Handle Mit dem Handler können Sie Message </ font> und ausführbare Objekte (z. B. Runnable) erstellen, die der MessageQueue </ font> des Threads zugeordnet sind. Sie können es senden und verarbeiten.

Eine Instanz von Handler ist einem einzelnen Thread und der Nachrichtenwarteschlange dieses Threads zugeordnet.

Wenn Sie einen neuen Handler erstellen, wird der Handler dem erzeugten Thread und seiner Nachrichtenwarteschlange zugewiesen. Der Handler kann dann die Nachricht und die ausführbare Nachrichtenwarteschlange zustellen und sie aus der Warteschlange entfernen und die Nachricht ausführen.

Verwendung des Haupthandlers

  • Planen Sie eine Nachricht und machen Sie sie zum geplanten Zeitpunkt ausführbar
  • Warteschlange für die Nachricht, die in einem separaten Thread ausgeführt werden soll

Planen Sie eine Nachricht

Zu verwendende Methode

Post Version post(Runnable)/postAtTime(java.lang.Runnable,long)/postDelayed(Runnable,Object,long)

Send Message Version sendEmptyMessege(int)/sendMessage(Message)/sendMessageAtTime(Message,long)/sendmessageDelayed(Message,long)

Die Post-Version stellt eine ausführbare Datei in die Warteschlange, wenn sie empfangen wird.

Die SendMassege-Version stellt Nachrichtenobjekte in die Warteschlange. Das Nachrichtenobjekt enthält eine Sammlung von Daten, die in der HandleMessage (Message) -Methode des Handlers verwendet werden. (HandleMessage (Massage) implementiert eine Unterklasse von Handler)

Durch das Posten oder Senden eines Handlers können Sie ihn verarbeiten, sobald die Nachrichtenwarteschlange bereit ist. Sie können auch die Verzögerung der Verarbeitung und die Ausführungszeit angeben.

Später werde ich die Implementierung von Timing-Operationen wie Timeout-Verarbeitung und Ticks (timer-like) erläutern.

Wenn die Anwendung ausgeführt wird, wird der Hauptthread zu einem dedizierten Thread zum Ausführen der Nachrichtenwarteschlange. Nachrichtenwarteschlangen verwalten Anwendungsobjekte der obersten Ebene wie Aktivitäten, Broadcasts und Empfänger sowie die von ihnen erstellten Fenster.

Mit Handler können Sie einen weiteren Thread für die Kommunikation mit der Hauptanwendung erstellen. Verwenden Sie dazu im Voraus die Methoden post und sendMessage.

Runnables und Nachrichten werden in der Nachrichtenwarteschlange des Handlers geplant und zum entsprechenden Zeitpunkt ausgeführt.


Handler-Zusammenfassung

■ ** Thread ** Klassenerweiterung | ** Runnable ** Schnittstellenvererbung ** Kommunikation mit UI-Thread **   view#post(Runnable)   View#postDelayed(Runnable.long)   runOnUiThread(Runnable) ■ ** AsyncTask ** -Klasse ** Verarbeitung und Kommunikation ** Mit execute (), doInBackground (), postExecute () usw. ■ ** Handler ** Klasse ** Kommunikation zwischen Multithreads ** Verantwortlich für die Kommunikation zwischen separat erstellten Threads   Message   Runnable

Handler-Zusammenfassung Zusammenfassung

class android.os.Handler

Handler ermöglicht die Kommunikation zwischen UI-Threads und Worker-Threads!

MessageQueue </ font> </ strong> (stapelt und speichert Nachrichten und Runnables) und ruft Nachrichten und Runnables aus MessageQueue in dem Thread ab, der die Handler-Instanz erstellt hat > Generieren Sie Looper </ font> </ strong>. Der Handler realisiert die Kommunikation zwischen Threads, sodass er anscheinend so konzipiert ist, dass er von anderen Threads referenziert werden kann </ font>.

Eine Instanz von Handler ist dem erzeugten Thread und der Nachrichtenwarteschlange zugeordnet und gibt true zurück, wenn eine Nachricht usw. zur Warteschlange hinzugefügt wird. Wenn Looper vor Ablauf der angegebenen Zeit beendet wird, wird Runnable abgebrochen und wird zu False. Wenn also False angezeigt wird, ist die Nachrichtenwarteschlange möglicherweise beendet!

Handler-Kommunikation

  • Verwendung der Nachricht
  • So verwenden Sie Runnable

Der Handler bietet eine Möglichkeit, Informationen zwischen bereits erstellten Threads zu kommunizieren. Es realisiert die Kommunikation zwischen Worker-Threads sowie UI-Threads.

Wenn Sie Message verwenden, verarbeitet Looper handleMessage, und wenn Sie Runnable verwenden, wird Runnable auf der UI-Seite ausgeführt.

###### Fall 1 von Handler und Nachricht

Message


public class MainActivity extends AppCompatActivity {

    TextView textView;

    //UI-Thread(MainActivity)Erstellen Sie eine Handler-Instanz mit
    //Jetzt sind sowohl MessageQueue als auch Looper UI-Threads.
    //Da der Instanzhandler von einem anderen Thread aus referenziert werden kann
    //Wenn Sie in einem anderen Thread auf den Handler verweisen und eine Nachricht posten
    //UI-Thread (MainActivity)Und Looper erledigt das für Sie!
    //Es ist cool! !!
    //Dann kommen Sie bitte zum Handler!
    Handler handler = new MyHandler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView1);

        MyLovelyMessage();
    }

    private void MyLovelyMessage() {
        //UI-Thread (MainActivity)Greifen Sie auf den in generierten Handler zu
        //Legen Sie die Nachricht in den Handler und senden Sie die Nachricht!
        //Der UI-Thread Looper sollte jetzt gut funktionieren!
        Message message = handler.obtainMessage(1);
        handler.sendMessage(message);
    }

    class MyHandler extends Handler{
        @Override
        public void handleMessage(Message message){
            //Definiert, was das Handle im UI-Thread tut
            //Es wird automatisch von Looper ausgeführt!
            String msg = String.valueOf(message.what);
            textView.setText(msg);
        }
    }
}

Vereinfachen Sie den obigen Code als interne Funktion

Message


public class MainActivity extends AppCompatActivity {

    TextView textView;

    Handler handler = new Handler(){
      @Override
      public void handleMessage(Message message){
          String msg = String.valueOf(message.what);
          textView.setText(msg);
      }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView1);

        MyLovelyRunnable();
    }

    private void MyLovelyRunnable() {
        Message message = handler.obtainMessage(1);
        handler.sendMessage(message);
    }
}
Beispiel mit Handler und Runnable
public class MainActivity extends AppCompatActivity {

    TextView textView;

    //Handler zum UI-Thread(MainAvtivity.class)Generieren mit
    //Jetzt befinden sich sowohl MessageQueue als auch Looper in diesem Thread(UI-Thread)Verknüpft mit
    //
    //Da die Handler-Instanz auch von anderen Threads aus referenziert werden kann
    //In einem anderen Thread mit dem Instanzhandler
    //In diesem Thread ausführbar(UI-Thread)Wenn du es gibst
    //Dieser Thread(UI-Thread-Seite)Kann Runnable ausführen
    //Es ist schön!
    //Jetzt erstellen wir eine Instanz von Handler! !!
    Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView1);

        MyLovelyHandler();

    }

    private void MyLovelyHandler(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                //UI-Thread(MainActivity)Die in erstellte Handler-Instanz
                //Kann von anderen Threads referenziert werden
                //Setzen Sie Runnable auf den Instanzhandler
                //UI-Thread (MainActivity)Lassen Sie es uns übergeben und verarbeiten lassen!
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("I Love Handler");
                    }
                });
            }
        }).start();
    }
}


Handler und Service: Ein Beispiel für die Aufteilung einer Datei in mehrere Teile

Mindestziel: api28 oder höher.

Erstellte Datei

  • MainActivity.java
    Erstellen Sie eine Handler-Instanz
    Führen Sie den Vordergrunddienst aus
  • MyService.java
    Erstellen Sie eine Nachricht und senden Sie eine Nachricht
  • MyHandler sendMessage Verarbeitet die gesendete Nachricht
Wenn ich Service mit Vordergrund aufrufe, stürzt es ab, es sei denn, ich starte Vordergrund (int, Benachrichtigung) auf der Serviceseite innerhalb von 5 Sekunden. Da der Code jedoch lang ist, werde ich ihn diesmal nicht beschreiben und er wird abstürzen, sorry.

MainActivity.java


public class MainActivity extends AppCompatActivity {
    public static TextView textView;

    //Erstellen Sie ein Handler-Objekt und machen Sie MessageQueue und Looper zu einem UI-Thread!
    //Dadurch wird die an das Handle-Objekt gesendete Nachricht in der MessageQueue gespeichert
    //Looper wird es herausnehmen und verarbeiten! (Der Inhalt des Prozesses ist MyHandler.Definiere es in der Klasse! )
    static MyHandler myHandler = new MyHandler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView);

        //Erstellen Sie ein Intent-Objekt und rufen Sie den Service an!
        Intent intent = new Intent(this,MyService.class);
        startForegroundService(intent);

    }
}

MyService.java


public class MyService extends Service {
    public MyService() {
    }

    @Override
    public int onStartCommand(Intent intent,int flags,int startid){
        //SendMessage, indem Sie eine Nachricht in das Handle-Objekt von MainActivity einfügen!!
        //Das Ziel ist MessageQueue des UI-Threads!
        //Danach ist Looper MyHandler.Klasse ausführen und verarbeiten!!
        Message message = MainActivity.myHandler.obtainMessage(1);
        MainActivity.myHandler.sendMessage(message);
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

MyHandler.java


//In MessageQueue des UI-Threads gespeicherte Nachricht
//Der UI-Thread Looper hat die folgende handleMessage()Wird durchgeführt!

public class MyHandler extends Handler {
    @Override
    public void handleMessage(Message message){
        String msg = String.valueOf(message.what);
        MainActivity.textView.setText(msg);
    }
}
Beispielcode für den Timer-Fall in Handler Runnable Service

Ich durfte mich beziehen. Vielen Dank. Hier Aber ich habe nicht verstanden, warum `myHandler.postDelayed (runnnable, milli) zweimal aufgerufen wurde.

<Übersicht> Es verarbeitet keine Benachrichtigungen und stürzt daher sofort ab. Wechseln Sie automatisch zum Vordergrunddienst, wenn die App gestartet wird ForegroundService, Timer-Verarbeitung mit handler.postDeployed (ausführbar, Mühle) Setzen Sie die Zählung mit der Starttaste fort Stoppen Sie die Zählung mit der Stopptaste

MainActivity.java


public class MainActivity extends AppCompatActivity {
    public static TextView textView;
    static Handler myHandler = new Handler();
    boolean signal =false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnStart= findViewById(R.id.btnStart);
        Button btnStop = findViewById(R.id.btnStop);
        textView = findViewById(R.id.textView);

        final Intent intent = new Intent(this,MyService.class);
        startForegroundService(intent);
        
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(signal == false){
                    MyService.runnable.run();
                    signal = true;
                }
            }
        });

        btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myHandler.removeCallbacks(MyService.runnable);
                signal = false;
            }
        });
    }
}

MyService.java


public class MyService extends Service {
    static Runnable runnable;
    public MyService() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startid) {

        runnable = new Runnable() {
            int i=0;
            @Override
            public void run() {
                i++;
                String st = String.valueOf(i);
                MainActivity.textView.setText(st);
                MainActivity.myHandler.postDelayed(this,1000);
            }
        };
        
//        MainActivity.myHandler.postDelayed(runnable,1000);
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Recommended Posts