【Android】メインスレッドに素早く切り替えてUIを更新する方法
11478 ワード
これは最近ネットを見て、サブスレッドでUIを更新する方法で、多くの説がありますが、あまり全面的ではありません.ここで私は総括の全面的ないくつかをやり遂げることを努力して、后で自分に対して、みんなに対してすべていくつか助けがあることを望みます.
方法1:view.post(Runnable action)
このメソッドがサブスレッドにある場合
これはviewが持参した方法で、比較的簡単で、もしあなたのサブスレッドの中で更新するviewを得ることができるならば、この方法で更新することができます.
もう一つの方法があるpostDelayed(Runnable action,long delayMillis)は、送信を遅延させるために使用される.
方法2:activity.runOnUiThread(Runnable action)
このメソッドがサブスレッドにある場合
注意:contextオブジェクトがメインスレッドのMainActivityの場合、このように強く回転することができます.
コンテキストがない場合は、次の方法を試してみます.1.用view.getContext()はコンテキストを得ることができます.2.contextをスキップしてnew Activity()をそのまま使用する.runOnUIThread(Runnable action)を使用して、プライマリ・スレッドに切り替えます.
方法3:Handlerメカニズム
まずメインスレッドでHandler,Handler mainHandler=new Handler()を定義する.(メインスレッドを操作するには、メインスレッドで定義する必要があります.他の場所で宣言を定義する場合は、このようにHandler mainHandler=new Handler(Looper.getMainLooper()と書き、メインスレッドのLooperとQueueを取得します)
Handlerを手に入れると簡単です.handlerを使います.Post(Runnable)メソッドは、handlerに依存するメッセージキュー(すなわち、プライマリスレッドメッセージキュー)にメッセージ処理を配置する.
(1):このメソッドがサブスレッドにある場合
Handlerには次の方法があります.1.postAtTime(Runnable r, long uptimeMillis);//ある時点でメッセージ2を送信.postAtDelayed(Runnable r, long delayMillis);//遅延delayMillisミリ秒再送信メッセージ
(2):メインスレッドで
その後mainHandlerをパラメータとして各クラス間に渡すことができ,UIを更新する必要がある場合,sendMessageの一連のメソッドを呼び出してhandleMessageでの操作を実行することができる.
サブスレッドにいるとします
上記のコードは、メッセージIDを送信しただけで、他のパラメータは送信されません.パラメータを渡すには、次のようにします.
まとめ:msg.objの機能は比較的に強く、Bundleを利用してデータを転送すると、効率が高く、メモリを節約できます.個人的には,伝達データの複雑さから,単純から複雑の順に用い,arg 1,setData(),objと考えられる.もっといいです.
もちろん、不要なコードを減らすために、簡略化された方法sendEmptyMessage(int what)を使用することができます.
メッセージを送信する他の方法は、次のとおりです.
方法4:AsyncTaskの使用
注意:doInBackgroundメソッドはサブスレッドにあるので、このメソッドでは時間のかかる操作を実行します.同時に、その戻り結果がonPostExecuteメソッドに渡されるため、onPostExecuteメソッドはUIスレッドで動作し、このメソッドでuiを更新し、uiを非同期で更新する目的を達成します.
Androidの非同期ロードデータとuiの更新については、AsyncTaskの非同期タスクだけでなく、多くのオープンソースのネットワークフレームワークを選択することができます.例えば、クリックしてより多くのxUtils 3、AsyncHttpClient、Okhttp、Volley、....これらの優れたネットワークフレームワークは、uiを非同期で更新することを非常に簡単にし、効率と性能も非常に高いです.もちろん、これらのネットワークフレームワークは決してこのような機能だけではありません.UIを非同期で更新するのは彼らの氷山の一角にすぎません.
androidネットワークフレームワークの詳細はこちらをクリックしてください
方法1:view.post(Runnable action)
このメソッドがサブスレッドにある場合
textView.post(new Runnable() {
@Override
public void run() {
textView.setText(" textView");
//
imageView.setBackgroundResource(R.drawable.update);
}
});
これはviewが持参した方法で、比較的簡単で、もしあなたのサブスレッドの中で更新するviewを得ることができるならば、この方法で更新することができます.
もう一つの方法があるpostDelayed(Runnable action,long delayMillis)は、送信を遅延させるために使用される.
方法2:activity.runOnUiThread(Runnable action)
このメソッドがサブスレッドにある場合
注意:contextオブジェクトがメインスレッドのMainActivityの場合、このように強く回転することができます.
public void updateUI(final Context context) {
((MainActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
// , UI
}
});
}
コンテキストがない場合は、次の方法を試してみます.1.用view.getContext()はコンテキストを得ることができます.2.contextをスキップしてnew Activity()をそのまま使用する.runOnUIThread(Runnable action)を使用して、プライマリ・スレッドに切り替えます.
方法3:Handlerメカニズム
まずメインスレッドでHandler,Handler mainHandler=new Handler()を定義する.(メインスレッドを操作するには、メインスレッドで定義する必要があります.他の場所で宣言を定義する場合は、このようにHandler mainHandler=new Handler(Looper.getMainLooper()と書き、メインスレッドのLooperとQueueを取得します)
Handlerを手に入れると簡単です.handlerを使います.Post(Runnable)メソッドは、handlerに依存するメッセージキュー(すなわち、プライマリスレッドメッセージキュー)にメッセージ処理を配置する.
(1):このメソッドがサブスレッドにある場合
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(new Runnable() {
@Override
public void run() {
// , UI
}
});
Handlerには次の方法があります.1.postAtTime(Runnable r, long uptimeMillis);//ある時点でメッセージ2を送信.postAtDelayed(Runnable r, long delayMillis);//遅延delayMillisミリ秒再送信メッセージ
(2):メインスレッドで
Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case 0:
// UI
break;
case 1:
// UI
break;
default:
break;
}
}
}
その後mainHandlerをパラメータとして各クラス間に渡すことができ,UIを更新する必要がある場合,sendMessageの一連のメソッドを呼び出してhandleMessageでの操作を実行することができる.
サブスレッドにいるとします
/**
* , obtainMessage() , , 。
* Messenger msg=new Messenger() , , !
* , 。( )
*/
Message msg = myHandler.obtainMessage();
msg.what = 0; //
myHandler.sendMessage(msg); //
上記のコードは、メッセージIDを送信しただけで、他のパラメータは送信されません.パラメータを渡すには、次のようにします.
msg.what = 1; //
msg.arg1=2; // , , arg1 arg2, Bundle 。
msg.arg2=3; //
Bundle bundle=new Bundle();
bundle.putString("dd","adfasd");
bundle.putInt("love",5);
msg.setData(bundle);
msg.obj=bundle; // Object
myHandler.sendMessage(msg); //
まとめ:msg.objの機能は比較的に強く、Bundleを利用してデータを転送すると、効率が高く、メモリを節約できます.個人的には,伝達データの複雑さから,単純から複雑の順に用い,arg 1,setData(),objと考えられる.もっといいです.
もちろん、不要なコードを減らすために、簡略化された方法sendEmptyMessage(int what)を使用することができます.
myHandler.sendEmptyMessage(0); //
メッセージを送信する他の方法は、次のとおりです.
endEmptyMessageAtTime(int what, long uptimeMillis); //
sendEmptyMessageDelayed(int what, long delayMillis); //
sendMessageAtTime(Message msg, long uptimeMillis); //
sendMessageDelayed(Message msg, long delayMillis); //
sendMessageAtFrontOfQueue(Message msg); // ( )
方法4:AsyncTaskの使用
/**
* :onPreExecute, doInBackground, onPostExecute
*/
private class MyAsyncTask extends AsyncTask<String, Integer, String> {
/**
*
* execute()
* UI
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
System.out.println("MyAsyncTask.onPreExecute");
}
/**
* , ,
* publishProgress(Progress... values) 。
*/
@Override
protected String doInBackground(String... params) {
System.out.println("MyAsyncTask.doInBackground");
//
int count = 0;
for (int i = 0; i < 10; i++) {
try {
count++;
publishProgress((count % 100) * 10);
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// publishProgress((int) ((count / (float) total) * 100));
return " ";
}
/**
*
* publishProgress(Progress... values) , , UI
*/
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
textView.setText("loading..." + values[0] + "%");
System.out.println("MyAsyncTask.onProgressUpdate");
}
/**
* , ,
* , UI 。
*/
@Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
System.out.println("MyAsyncTask.onPostExecute aVoid=" + aVoid);
textView.setText(aVoid);
}
/**
*
* , 。 UI
*/
@Override
protected void onCancelled() {
super.onCancelled();
System.out.println("MyAsyncTask.onCancelled");
progressBar.setProgress(0);
textView.setText("0");
}
@Override
protected void onCancelled(String s) {
super.onCancelled(s);
}
}
注意:doInBackgroundメソッドはサブスレッドにあるので、このメソッドでは時間のかかる操作を実行します.同時に、その戻り結果がonPostExecuteメソッドに渡されるため、onPostExecuteメソッドはUIスレッドで動作し、このメソッドでuiを更新し、uiを非同期で更新する目的を達成します.
Androidの非同期ロードデータとuiの更新については、AsyncTaskの非同期タスクだけでなく、多くのオープンソースのネットワークフレームワークを選択することができます.例えば、クリックしてより多くのxUtils 3、AsyncHttpClient、Okhttp、Volley、....これらの優れたネットワークフレームワークは、uiを非同期で更新することを非常に簡単にし、効率と性能も非常に高いです.もちろん、これらのネットワークフレームワークは決してこのような機能だけではありません.UIを非同期で更新するのは彼らの氷山の一角にすぎません.
androidネットワークフレームワークの詳細はこちらをクリックしてください