私はAndroidの初心者で、UI-Threadを使おうとしているので、簡単なテストアクティビティを書きました。ボタンをクリックするとアプリが反応しなくなるため、誤解したと思います。
public class TestActivity extends Activity {
Button btn;
int i = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
runThread();
}
});
}
private void runThread(){
runOnUiThread (new Thread(new Runnable() {
public void run() {
while(i++ < 1000){
btn.setText("#"+i);
try {
Thread.sleep(300);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}));
}
}
以下はrunThread
関数の抜粋です。
private void runThread() {
new Thread() {
public void run() {
while (i++ < 1000) {
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
btn.setText("#" + i);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
それを関数としてラップしてから、バックグラウンドスレッドからこの関数を呼び出します。
public void debugMsg(String msg) {
final String str = msg;
runOnUiThread(new Runnable() {
@Override
public void run() {
mInfo.setText(str);
}
});
}
あなたはそれを前後に持っています。ボタンをクリックするとrunOnUiThread()
が呼び出されますが、クリックハンドラは既にUIスレッド上で実行されているため、これは必要ありません。それから、runOnUiThread()
内のコードは新しいバックグラウンドスレッドを起動しています。そこで、UI操作を実行しようとしますが、失敗します。
代わりに、クリックハンドラから直接バックグラウンドスレッドを起動してください。次に、btn.setText()
への呼び出しの内側にrunOnUiThread()
への呼び出しをラップします。
runOnUiThread(new Runnable() {
public void run() {
//Do something on UiThread
}
});
RunOnUiThread()の使用方法はいくつかありますが、全部見てみましょう。
これはAndroidBasicThreadActivityと呼ばれる私のメインスレッド(UIスレッド)で、さまざまな方法でワーカースレッドから更新します -
public class AndroidBasicThreadActivity extends AppCompatActivity
{
public static TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_Android_basic_thread);
textView = (TextView) findViewById(R.id.textview);
MyAndroidThread myTask = new MyAndroidThread(AndroidBasicThreadActivity.this);
Thread t1 = new Thread(myTask, "Bajrang");
t1.start();
}
}
1)WorkerスレッドにActivityのインスタンスを引数として渡すことで
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
@Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
activity.runOnUiThread(new Runnable()
{
@Override
public void run()
{
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
2.)ワーカースレッドでViewのpost(Runnable runnable)メソッドを使用する
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
@Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
AndroidBasicThreadActivity.textView.post(new Runnable()
{
@Override
public void run()
{
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
3。)Android.osパッケージのHandlerクラスを使用することでコンテキスト(this/getApplicationContext())またはアクティビティのインスタンス(AndroidBasicThreadActivity)がない場合.this)それから、以下のようにHandlerクラスを使う必要があります -
class MyAndroidThread implements Runnable
{
Activity activity;
public MyAndroidThread(Activity activity)
{
this.activity = activity;
}
@Override
public void run()
{
//perform heavy task here and finally update the UI with result this way -
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
}
});
}
}
フラグメントで使用する場合は、単純に書く
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
//Do something on UiThread
}
});
これ:
@UiThread
public void logMsg(final String msg) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gifImageView = (GifImageView) findViewById(R.id.GifImageView);
gifImageView.setGifImageResource(R.drawable.success1);
new Thread(new Runnable() {
@Override
public void run() {
try {
//dummy delay for 2 second
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//update ui on UI thread
runOnUiThread(new Runnable() {
@Override
public void run() {
gifImageView.setGifImageResource(R.drawable.success);
}
});
}
}).start();
}
これは私がそれを使用する方法です:
runOnUiThread(new Runnable() {
@Override
public void run() {
//Do something on UiThread
}
});
このサンプルから使用できます。
次の例では、この機能を使用して、バックグラウンドスレッドによって処理された同義語検索の結果を公開します。
OnCreateアクティビティのコールバック中に目標を達成するために、作成したスレッドでsearchTaskを実行するようにonClickListenerを設定します。
ユーザーが[検索]ボタンをクリックすると、R.id.wordEt EditTextに入力されたWordを検索してRunnableを実行するスレッドを開始するRunnable匿名クラスが作成されます。
検索が完了したら、Runnable SetSynonymResultのインスタンスを作成して、UIスレッドを介してシノニムTextViewに結果を公開します。
この手法は、特にActivityインスタンスにアクセスできない場合は特に便利ではありません。したがって、以降の章では、バックグラウンドコンピューティングタスクからUIを更新するための、よりシンプルでクリーンなテクニックについて説明します。
public class MainActivity extends AppCompatActivity {
class SetSynonymResult implements Runnable {
String synonym;
SetSynonymResult(String synonym) {
this.synonym = synonym;
}
public void run() {
Log.d("AsyncAndroid", String.format("Sending synonym result %s on %d",
synonym, Thread.currentThread().getId()) + " !");
TextView tv = (TextView) findViewById(R.id.synonymTv);
tv.setText(this.synonym);
}
}
;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button search = (Button) findViewById(R.id.searchBut);
final EditText Word = (EditText) findViewById(R.id.wordEt);
search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Runnable searchTask = new Runnable() {
@Override
public void run() {
String result = searchSynomim(Word.getText().toString());
Log.d("AsyncAndroid", String.format("Searching for synonym for %s on %s",
Word.getText(), Thread.currentThread().getName()));
runOnUiThread(new SetSynonymResult(result));
}
};
Thread thread = new Thread(searchTask);
thread.start();
}
});
}
static int i = 0;
String searchSynomim(String Word) {
return ++i % 2 == 0 ? "fake" : "mock";
}
}
出典: