XamarinスタディノートA14(Android AsyncTaskおよびRunOnUiThread)



Xamarin Study Notes A14 Android Asynctask



(少しのxamarinを学ぶたびに、学習ノートとビデオを作成して、記憶を深め、知識を統合します)

何か問題があれば訂正してください。



前書き

AsyncTaskクラスとActivity.RunOnUiThread()メソッドは、Hanlderメッセージ処理のカプセル化です。



アンドロイドで1.時間のかかるタスクは、子スレッドでのみ実行できます。 2. UIの更新は、メインスレッドでのみ実行できます。したがって、非同期メッセージ処理メカニズムを使用します

方法/クラス

説明

効果

Activity.RunOnUiThread(コールバック方式)

ハンドラー+メッセージパッケージ



メッセージを作成してコールバックメソッドに関連付け、メッセージキューに送信します。

AsyncTaskクラス

ハンドラー+メッセージ+スレッドパッケージ

メッセージを作成し、スレッドプールの子スレッドを使用して、メッセージをキューに送信し、最後に対応するコールバックメソッドを実行します。

まず、Activity.RunOnUiThread()メソッドを見てください

アンドロイドからソースコードから抽出した主な部分は次のとおりです。

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 } }

主にマークのシリアル番号に依存し、実行しますrunOnUiThread最初にメソッドを設定します役職メソッド、投稿呼び出されたメソッドgetPostMessageメッセージを作成する方法オブジェクトと関連するコールバックメソッド、そして最終的に渡されますenqueueMessageメッセージオブジェクトはメッセージキューに送信されます。次に、メインスレッドのLooperオブジェクトは、MessageQueueからメッセージを自動的に取得し、メッセージオブジェクトに関連付けられたコールバックメソッドを呼び出します。

たとえば、次のように使用して、コードの一部を貼り付けることができます。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 } }

次に、AsyncTaskクラスを見てください

アンドロイドを抽出しないでくださいソースコードが多すぎて抽出するのは簡単ではありません。また、ハンドラメッセージメカニズムを内部にカプセル化します。上記のように自分でスレッドを作成する必要はありません。内部でスレッドを作成し、スレッドプールを使用してパフォーマンスを向上させます。

このクラスの定義を開くと、これが抽象クラスであることがわかります。書き直すには、主に5つのメソッドがあります。

//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() }
このクラスを具体的に使用して、コードを貼り付けましょう
//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() //} }
その後、アクティビティで呼び戻す
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 } }

最終結果を以下に示します。



コードとビデオは私がアップロードしたCSDNリソースにあります http://download.csdn.net/download/junshangshui/10048297