Android에서 runOnUiThread를 어떻게 사용합니까?


157

저는 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();
                    }
                }
             }
        }));
    }
}

답변:


204

아래는 수정 된 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();
}

이것은 거의 즉시 가비지 수집되지 않았습니까? 아마 당신은 Thread ()에 대한 참조를 유지해야 할 것입니다.
Nick

14
@Nick : 가비지 콜렉터는 스택을 감시합니다. 즉, 스레드가 실행 중일 때는 GC되지 않습니다.
Miro Kropacek

@Vipul, 전화 회전에 대한 질문이 있습니다. 전화를 돌리면이 스레드가 실행되고 새로운 스레드가 생성되지 않습니다. 전화기를 회전 한 후 새 스레드가 생성되지 않도록하는 방법에 대한 힌트를 제공 할 수 있습니까?
user1836957

89

함수로 감싸고 배경 스레드 에서이 함수를 호출하십시오.

public void debugMsg(String msg) {
    final String str = msg;
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mInfo.setText(str);
        }
    });
}

3
외부 범위 ( final)의 데이터에 액세스하는 방법을 보여주는 의견
mariotomo

27

당신은 그것을 앞뒤로 가지고 있습니다. runOnUiThread()클릭 처리기가 이미 UI 스레드에서 실행 중이므로 버튼 클릭으로에 대한 호출 이 필요하지만 필요하지 않습니다. 그런 다음 코드에서 runOnUiThread()UI 작업을 시도하는 새 백그라운드 스레드를 시작하면 실패합니다.

대신 클릭 핸들러에서 직접 백그라운드 스레드를 시작하십시오. 그런 다음 통화를의 btn.setText()내부 통화로 래핑합니다 runOnUiThread().


클릭 핸들러가 이미 UI 스레드에 있다는 것은 사실 runOnUiThread()이지만 호출 은 불필요하지만 무해해야합니다. 해당 메소드의 Javadoc은 "UI 스레드에서 지정된 조치를 실행합니다. 현재 스레드가 UI 스레드 인 경우 조치가 즉시 실행됩니다. 현재 스레드가 UI 스레드가 아닌 경우 조치는 이벤트 큐에 게시됩니다. UI 스레드의
k2col

15
runOnUiThread(new Runnable() {
                public void run() {
                //Do something on UiThread
            }
        });

10

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.) 작업자 스레드에서 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 ()) 또는 Activity 인스턴스 (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.");
        }
    });
  }
}

감사합니다 .. runOnUIThread 활동에 대해 반복하는 대신 가능한 모든 호출 방법을 언급했습니다.
arun

감사합니다 .. runOnUIThread 활동에 대해 반복하는 대신 가능한 모든 호출 방법을 언급했습니다.
arun

6

조각으로 사용하는 경우 간단히 작성하십시오.

getActivity().runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // Do something on UiThread
    }
});

1

너의 이것 :

@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");


            }
        });
    }

1

우리는 Worker Thread를 사용하여 앱을 더 매끄럽게 만들고 ANR을 피합니다. 워커 트레드에서 무거운 프로세스를 수행 한 후 UI를 업데이트해야 할 수도 있습니다. UI는 UI 스레드에서만 업데이트 할 수 있습니다. 이러한 경우 Handler를 사용하거나 runOnUiThread에는 UI Thread에서 실행되는 Runnable run 메소드가 있습니다. onClick 메소드는 UI 스레드에서 실행되므로 runOnUiThread를 사용할 필요가 없습니다.

코 틀린 사용

활동 중에

this.runOnUiThread {
      // Do stuff
}

조각에서,

activity?.runOnUiThread {
      // Do stuff
}

자바를 사용하여 ,

this.runOnUiThread(new Runnable() {
     void run() {
         // Do stuff
     }
});

0

이 샘플에서 사용할 수 있습니다.

다음 예에서는이 기능을 사용하여 백그라운드 스레드로 처리 된 동의어 검색의 결과를 공개합니다.

OnCreate 액티비티 콜백 동안 목표를 달성하기 위해 생성 된 스레드에서 searchTask를 실행하도록 onClickListener를 설정합니다.

사용자가 검색 버튼을 클릭하면 R.id.wordEt EditText에 입력 된 단어를 검색하고 스레드를 시작하여 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";
    }
}

출처 :

비동기 안드로이드 프로그래밍 Helder Vasconcelos


0

이것이 내가 사용하는 방법입니다.

runOnUiThread(new Runnable() {
                @Override
                public void run() {
                //Do something on UiThread
            }
        });

0
  @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();

    }

0

이 시도: getActivity().runOnUiThread(new Runnable...

왜냐하면:

1) runOnUiThread 호출에서 암시 적 인 것은 조각이 아닌 AsyncTask를 참조하고 있습니다.

2) 조각에는 runOnUiThread가 없습니다.

그러나 활동은 않습니다.

이미 메인 스레드에있는 경우 Activity는 Runnable을 실행합니다. 그렇지 않으면 Handler를 사용합니다. 이 컨텍스트에 대해 걱정하지 않으려는 경우 조각에서 처리기를 구현할 수 있습니다. 실제로 매우 쉽습니다.

// 클래스 인스턴스

private Handler mHandler = new Handler(Looper.getMainLooper());

// 코드의 다른 곳

mHandler.post(<your runnable>);

// ^ 이것은 항상 메인 스레드의 다음 실행 루프에서 실행됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.