Uwagi dotyczące badania Xamarin A14 (Android AsyncTask i RunOnUiThread)
Xamarin Study Notes A14 Android Asynctask
(Za każdym razem, gdy nauczysz się trochę xamarin, zrób notatkę do nauki i wideo, aby pogłębić swoją pamięć i utrwalić swoją wiedzę)
Jeśli coś jest nie tak, proszę mnie poprawić.
Wprowadzenie
AsyncTaskKlasa i aktywność.RunOnUiThread ()Metody to hermetyzacja przetwarzania komunikatów Hanldera.
W systemie Android1. Czasochłonne zadania można wykonywać tylko w wątkach podrzędnych. 2. Aktualizacje interfejsu użytkownika mogą być wykonywane tylko w głównym wątku.Dlatego używaj asynchronicznego mechanizmu przetwarzania wiadomości
metoda/klasa | Opis | efekt |
Activity.RunOnUiThread (Metoda oddzwaniania) | Handler + MessagePakiet | Utwórz wiadomość i skojarz ją z metodą wywołania zwrotnego, a następnie wyślij do kolejki komunikatów. |
AsyncTaskklasa | Handler + wiadomość + wątekPakiet | Twórz wiadomości i używaj wątków potomnych puli wątków, wysyłaj wiadomości do kolejki, a na koniec wykonaj odpowiednią metodę wywołania zwrotnego. |
Najpierw spójrz na metodę Activity.RunOnUiThread ()
Z AndroidaGłówne części wyodrębnione z kodu źródłowego są następujące
public class Activity { //...Omit other codes... //1 public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action) } else { action.run() } } }
public class Handler{ //...Omit other codes... //2 public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0) } //3 private static Message getPostMessage(Runnable r) { Message m = Message.obtain()//Create a message m.callback = r //The callback method associated with the message is set here return m } //4 public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis <0) { delayMillis = 0 } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis) } //5 public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue if (queue == null) {return false} return enqueueMessage(queue, msg, uptimeMillis) } //6 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this return queue.enqueueMessage(msg, uptimeMillis)//Send the message to the message queue } //7 is executed on the main thread (automatically called) public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg)//Call the callback method associated with the message object } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return } } handleMessage(msg) } } //8 is executed on the main thread (automatically called) private static void handleCallback(Message message) { message.callback.run()//Call the callback method associated with the message object } }
Głównie zależy od numeru seryjnego znaku, wykonajrunOnUiThreadNajpierw skonfiguruj metodęPocztaMetoda, pocztaMetoda zwanagetPostMessageMetoda tworzenia wiadomościObiekt i skojarzona metoda wywołania zwrotnego, a na koniec przekazaneenqueueMessageWiadomośćObiekt jest wysyłany do kolejki komunikatów. Następnie obiekt Looper głównego wątku automatycznie pobiera wiadomość z MessageQueue i wywołuje metodę wywołania zwrotnego skojarzoną z obiektem wiadomości.
Na przykład możemy go użyć w ten sposób i wkleić część kodu:
private TextView textView private string address = 'http://www.hao123.com' public void OnClick(View v) { switch (v.Id) { //Request network data (remember to declare network permissions on the Applincation node of AndroidManifest.xml ) case Resource.Id.button1: new Thread(new ThreadStart( () => { #region Child thread execution request HttpURLConnection conn = null try { URL url = new URL(address) conn = (HttpURLConnection)url.OpenConnection() //Open the connection conn.RequestMethod = 'GET' conn.DoInput = true //allow to receive data, you can use conn.InputStream later Stream inStream = conn.InputStream //The actual request data string result using (StreamReader reader = new StreamReader(inStream, Encoding.UTF8)) { result = reader.ReadToEnd() } this.RunOnUiThread( //RunOnUiThread is essentially a package for Handler asynchronous message processing, //It creates a message object internally, and associates the following anonymous method to the message object, and then sends the message to the queue (executed in the child thread) //Finally, the Looper object running on the main thread will automatically fetch the message from the MessageQueue and execute the method associated with the message object (executed in the main thread) () => { Toast.MakeText(this, 'Request successful', ToastLength.Short).Show() textView.Text = result } //Update the UI on the main thread ) } catch (System.Exception e) { Toast.MakeText(this, 'Request error'+e.Message, ToastLength.Long).Show() } finally { if (conn != null) conn.Disconnect()//Close the connection } #endregion } )).Start() break } }
Następnie spójrz na klasę AsyncTask
Nie wyodrębniaj androidaKodu źródłowego jest za dużo i nie jest łatwo go wyodrębnić. Zawiera również wewnątrz mechanizm wiadomości Handler. Nie musisz samodzielnie tworzyć wątków, jak powyżej. Tworzy dla nas wątki wewnętrznie, a także wykorzystuje pule wątków do poprawy wydajności.
Otwórz definicję tej klasy, zobaczysz, że jest to klasa abstrakcyjna, istnieje głównie pięć metod, które możemy przepisać.
//Paradigm parameter 1 is the type of input parameter, parameter 2 is the type of the progress value, parameter 3 is the return value type of the task public abstract class AsyncTask : AsyncTask { public AsyncTask() //Start an asynchronous task public AsyncTask Execute(params TParams[] @params) // is called before the start of the asynchronous task (in the main thread) protected virtual void OnPreExecute() //(Run specific tasks in child threads) protected abstract TResult RunInBackground(params TParams[] @params) //Called when the progress changes (in the main thread) protected virtual void OnProgressUpdate(params TProgress[] values) //Called after the asynchronous task is executed (in the main thread) protected virtual void OnPostExecute(TResult result) //Called after the task is cancelled protected virtual void OnCancelled() }
Skorzystajmy specjalnie z tej klasy i wklejmy trochę kodu
//Asynchronous task processing public class MyTask: AsyncTask//Parameter 1 is the type of input parameter, parameter 2 is the type of progress value, parameter 3 is the return value type of the task { public interface IMyTask { void OnFinish(string result)//Define a callback method } private IMyTask _myTask public void SetLitener(IMyTask listener)//pass an object that implements the IMyTask interface to monitor the task result { _myTask = listener } //Called before the start of the asynchronous task (in the main thread) protected override void OnPreExecute() { Log.Debug('MyTask', 'OnPreExecute() is called before the asynchronous task starts') } //(Run specific tasks in child threads) //This method will create a child thread Thread, then perform tasks, and then send Message to the message queue. protected override string RunInBackground(params string[] @params)////Because params has the same name as the C# keyword params, so add @ symbol { Log.Debug('MyTask', 'RunInBackground() is called') HttpURLConnection conn = null try { string address = @params[0]//Retrieve the request address URL url = new URL(address) conn = (HttpURLConnection)url.OpenConnection() //Open the connection conn.RequestMethod = 'GET' conn.DoInput = true //allow to receive data, you can use conn.InputStream later Stream inStream = conn.InputStream //The actual request data string result using (StreamReader reader = new StreamReader(inStream, Encoding.UTF8)) { result = reader.ReadToEnd() } return result } catch { return '' } finally { if (conn != null) conn.Disconnect()//Close the connection } } //Called when the progress changes (in the main thread) //protected override void OnProgressUpdate(params int[] values) //{ // base.OnProgressUpdate(values) //} //Called after the asynchronous task is executed (in the main thread) protected override void OnPostExecute(string result) { Log.Debug('MyTask', 'OnPostExecute() is called after the asynchronous task is executed') if (_myTask!=null) { _myTask.OnFinish(result) //Execute callback method } } //Called after the task is cancelled //protected override void OnCancelled() //{ // base.OnCancelled() //} }
Następnie w AktywnościPrzywołać
public class SecondActivity : AppCompatActivity, IOnClickListener, MyTask.IMyTask { private TextView textView private string address = 'http://www.hao123.com' public void OnClick(View v) { switch (v.Id) { case Resource.Id.button1: MyTask myTask = new MyTask() myTask.SetLitener(this) myTask.Execute(address) //Start an asynchronous task break } } public void OnFinish(string result) { textView.Text = result //Display request result } }
Ostateczny wynik przedstawiono poniżej
Kod i wideo znajdują się w przesłanym przeze mnie zasobie CSDN http://download.csdn.net/download/junshangshui/10048297