Android'de runOnUiThread'i nasıl kullanıyoruz?


157

Android'de yeniyim ve UI-Thread'ı kullanmaya çalışıyorum, bu yüzden basit bir test etkinliği yazdım. Ama sanırım bir şeyi yanlış anladım, çünkü düğmeyi tıkladığınızda - uygulama artık yanıt vermiyor

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

Yanıtlar:


204

Aşağıda Düzeltilmiş runThreadİşlev Snippet'i bulunmaktadır .

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

Bu hemen toplanan Çöp değil miydi? Muhtemelen Thread ()
Nick

14
@Nick: çöp toplayıcı da yığını izler, yani iplik çalışırken GC'ed olmaz.
Miro Kropacek

@Vipul, telefon döndürme hakkında bir sorum vardı: Telefonumu döndürdüğümde bu iş parçacığı çalışır ve yeni bir iş parçacığı oluşturulur istiyorum. Telefon döndürüldüğünde yeni bir iş parçacığının oluşturulmasının nasıl önleneceğine dair bazı ipuçları verebilir misiniz?
user1836957

90

Sadece bir işlev olarak sarın, ardından bu işlevi arka plan iş parçacığından çağırın.

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

3
dış kapsamdaki verilere nasıl erişileceğini göstermek için seçildi ( final)
mariotomo

27

Önden arkaya aldınız. Düğme tıklamanız çağrı yapılmasına neden olur runOnUiThread(), ancak tıklama işleyicisi zaten kullanıcı arayüzü iş parçacığında çalışıyor olduğundan buna gerek yoktur. Ardından, kodunuz runOnUiThread()UI işlemlerini yapmaya çalıştığınız yeni bir arka plan iş parçacığı başlatıyor ve bu da başarısız oluyor.

Bunun yerine, arka plan iş parçacığını doğrudan tıklama işleyicinizden başlatın. Ardından, çağrıları btn.setText()çağrının içine kaydırın runOnUiThread().


Tıklama işleyicisinin zaten kullanıcı arayüzü iş parçacığında olduğu doğru olsa da, bir çağrı runOnUiThread()gereksizdir, ancak zararsız olmalıdır. Bu yöntem için Javadoc "UI iş parçacığında belirtilen eylemi çalıştırır. Geçerli iş parçacığı UI iş parçacığı ise, eylem hemen yürütülür. Geçerli iş parçacığı UI iş parçacığı değilse, eylem olay sırasına kaydedilir UI iş parçacığı. "
k2col

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

10

RunOnUiThread () kullanarak birkaç teknik vardır, hepsini görelim

Bu benim AndroidBasicThreadActivity adlı ana iş parçacığı (UI iş parçacığı) ve çeşitli şekillerde bir işçi iş parçacığından güncelleştirmek için gidiyorum -

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.) Faaliyet örneğini işçi iş parçacığında bir argüman olarak ileterek

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.) Çalışan iş parçacığında View'un post (Runnable runnable) yöntemini kullanarak

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 paketinden Handler sınıfını kullanarak Bağlam (this / getApplicationContext ()) veya Aktivite örneğini (AndroidBasicThreadActivity.this) yoksa, Handler sınıfını aşağıdaki gibi kullanmamız gerekir -

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.");
        }
    });
  }
}

Eyvallah .. runOnUIT hakkında daha fazla bilgi vermek yerine faaliyetin tüm olası yollarından bahsettiniz ..
arun

Eyvallah .. runOnUIT hakkında daha fazla bilgi vermek yerine faaliyetin tüm olası yollarından bahsettiniz ..
arun

6

Parça halinde kullanılıyorsa, sadece yazın

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

1

bu senin:

@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

Çalışanları İş Parçacığını kullanarak uygulamaları daha düzgün hale getirir ve ANR'lerden kaçınırız. İşçi Sırtı'ndaki ağır işlemden sonra kullanıcı arayüzünü güncellememiz gerekebilir. Kullanıcı arayüzü yalnızca kullanıcı arayüzü iş parçacığından güncellenebilir. Bu gibi durumlarda, Handler veya runOnUiThread kullanıyoruz, her ikisinde de UI İş Parçacığında çalışan bir Runnable çalıştırma yöntemi var. OnClick yöntemi UI iş parçacığında çalışır, bu nedenle burada runOnUiThread kullanmanıza gerek yoktur.

Kotlin Kullanımı

Etkinlikteyken,

this.runOnUiThread {
      // Do stuff
}

Fragment'tan,

activity?.runOnUiThread {
      // Do stuff
}

Java kullanarak ,

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

0

Bu örnekten kullanabilirsiniz:

Aşağıdaki örnekte, bu özelliği, bir arka plan iş parçacığı tarafından işlenen eş anlamlı aramanın sonucunu yayınlamak için kullanacağız.

OnCreate etkinliği geri araması sırasında hedefi gerçekleştirmek için onClickListener'ı oluşturulan bir iş parçacığında searchTask'ı çalıştıracak şekilde ayarlayacağız.

Kullanıcı Ara düğmesine tıkladığında, R.id.wordEt EditText yazılan sözcüğü arayan ve Runnable'ı çalıştırmak için iş parçacığını başlatan bir Runnable anonim sınıfı yaratacağız.

Arama tamamlandığında, sonucu UI iş parçacığı üzerindeki TextView eş anlamlısında geri yayınlamak için bir Runnable SetSynonymResult örneği oluşturacağız.

Bu teknik, özellikle bir Etkinlik örneğine erişimimiz olmadığında, bazen en uygun teknik değildir; bu nedenle, aşağıdaki bölümlerde, bir arka plan bilgi işlem görevinden kullanıcı arayüzünü güncellemek için daha basit ve daha temiz teknikleri tartışacağız.

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

Kaynak :

eşzamansız android programlama Helder Vasconcelos


0

Ben nasıl kullanacağım:

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

Bunu dene: getActivity().runOnUiThread(new Runnable...

Çünkü:

1) runOnUiThread çağrınızda örtük olan bu, parçanıza değil AsyncTask'a atıfta bulunuyor .

2) Parçanın runOnUiThread'i yok.

Ancak, Etkinlik yapar.

Etkinlik'in zaten ana iş parçacığındaysanız Runnable'ı yürüttüğünü unutmayın, aksi takdirde bir İşleyici kullanır. Bunun bağlamı hakkında endişelenmek istemiyorsanız, parçanızda bir işleyici uygulayabilirsiniz, aslında çok kolaydır:

// Bir sınıf örneği

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

// kodunuzdaki başka herhangi bir yer

mHandler.post(<your runnable>);

// ^ bu her zaman ana iş parçacığındaki bir sonraki çalıştırma döngüsünde çalıştırılır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.