Soru Android temel özellikleri: kullanıcı arabiriminde kod çalıştırma


UI iş parçacığı kod çalıştırma bakış açısında, arasında herhangi bir fark var mı:

MainActivity.this.runOnUiThread(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

veya

MainActivity.this.myView.post(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

ve

private class BackgroundTask extends AsyncTask<String, Void, Bitmap> {
    protected void onPostExecute(Bitmap result) {
        Log.d("UI thread", "I am the UI thread");
    }
}

376
2017-10-11 23:28


Menşei


Sorumu açıklığa kavuşturmak için: Bu kodların bir hizmet dizisinden, genellikle bir dinleyiciden çağrıldığını varsaydım. Ayrıca, AsynkTask'ın doInBackground () işlevinde veya ilk iki parçacığı önce çağrılan yeni bir görevde (...) gerçekleştirmek için ağır bir çalışma olduğunu düşündüm. Her neyse, AsyncTask'ın onPostExecute () öğesi, olay kuyruğunun sonuna yerleştirilir, değil mi? - Luky


Cevaplar:


Bunların hiçbiri tam olarak aynı değil, ancak hepsi aynı net etkiye sahip olacaklar.

İlk ile ikincisi arasındaki fark, eğer üzerinde kod yürütülürken ana uygulama iş parçacığı, ilk olanırunOnUiThread()) yürütecek Runnable hemen. İkinci olan (post()) her zaman Runnable Etkinlik kuyruğunun sonunda, ana uygulama iş parçacığı üzerinde olsanız bile.

Üçüncüsü, bir örnek oluşturup çalıştırdığınızı varsayarsak BackgroundTask, bir varsayılan no-op yürütmek için iş parçacığı havuzu dışında bir iş parçacığı kapma çok zaman harcayacak doInBackground()nihayetinde ne yapmak için post(). Bu, üçün en az verimli olanıdır. kullanım AsyncTask Aslında bir arka plan iş parçasında yapmak için iş varsa, sadece kullanımı için değil onPostExecute().


248
2017-10-11 23:33



Ayrıca dikkat edin AsyncTask.execute() UI iş parçacığı tüm arka plana taşımak sürece, bir UI iş parçacığı üzerinde UI iş parçacığı üzerinde sadece çalışan kod kullanımı için işe yaramazsa, bu seçeneği UI iş parçacığı çağrısı gerektirir doInBackground()ve kullan AsyncTask uygun şekilde. - kabuko
@kabuko aradığımı kontrol edebiliyorum AsyncTask UI iş parçacığı? - Neil Galiaskarov
@NeilGaliaskarov Bu katı bir seçenek gibi görünüyor: stackoverflow.com/a/7897562/1839500 - Dick Lucas
@NeilGaliaskarov boolean isUiThread = (Looper.getMainLooper().getThread() == Thread.currentThread()); - ban-geoengineering
@NeilGaliaskarov, M kullanımından daha büyük veya eşit sürümler için Looper.getMainLooper().isCurrentThread - Balu Sangem


Olanı seviyorum HPP yorumuherhangi bir parametre olmadan her yerde kullanılabilir:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

197
2017-08-11 19:01



Bu ne kadar verimli? Diğer seçenekler ile aynı mı? - EmmanuelMess


Kullanarak dördüncü yol var Handler

new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});

52
2017-10-11 23:36



postOnUiThread() kullanır Handler bunu yapmak için olsa :) - Alex Lockwood
Buna dikkat etmelisin. UI olmayan bir iş parçacığında bir işleyici oluşturursanız, UI iş parçacığına iletileri gönderirsiniz. Bir işleyici, oluşturulduğu iş parçacığına varsayılan ileti iletisine göre. - lujop
ana kullanıcı arayüzü iş parçacığı üzerinde yürütmek için new Handler(Looper.getMainLooper()).post(r)tercih edilen şekilde Looper.getMainLooper() ana, bir statik çağrı yapar postOnUiThread() bir örneği olmalı MainActivity kapsamında. - HPP
@HPP Bu yöntemi bilmiyordum, ne sahip olduğunuz ne de Aktiviteye sahip olmamanız için harika bir yol olacaktır. Harika çalışıyor! çok teşekkür ederim çok teşekkürler! - Sulfkain
@lujop Aynı, AsyncTask'ın onPreExecute geri arama yönteminde de geçerlidir. - Sreekanth Karumanaghat


Pomber'in cevabı kabul edilebilir, ancak tekrar tekrar yeni nesneler yaratmanın büyük bir hayranı değilim. En iyi çözümler daima bellek çengelini azaltmaya çalışanlardır. Evet, otomatik çöp toplama var, ancak bir mobil cihazda bellek koruması en iyi uygulamanın sınırları içinde kalıyor. Aşağıdaki kod bir serviste bir TextView güncellemektedir.

TextViewUpdater textViewUpdater = new TextViewUpdater();
Handler textViewUpdaterHandler = new Handler(Looper.getMainLooper());
private class TextViewUpdater implements Runnable{
    private String txt;
    @Override
    public void run() {
        searchResultTextView.setText(txt);
    }
    public void setText(String txt){
        this.txt = txt;
    }

}

Bunun gibi herhangi bir yerden kullanılabilir:

textViewUpdater.setText("Hello");
        textViewUpdaterHandler.post(textViewUpdater);

17
2018-01-05 09:24



GC ve nesne oluşturma konusunda +1. NASIL, mutlaka katılıyorum The best solutions are always the ones that try to mitigate memory hog. İçin başka birçok kriter var bestve bu hafif bir kokusu var premature optimization. Yani, bu kadar fazla sayıda nesneyi oluşturduğunuzu bilmediğiniz sürece, bir sorun (uygulamanızın muhtemelen çöp ürettiği diğer on bin yolla karşılaştırılır) sorunudur. best En basit (anlaşılması kolay) kodu yazmak ve başka bir göreve geçmek. - ToolmakerSteve
BTW, textViewUpdaterHandler gibi daha iyi bir şey olurdu uiHandler veya mainHandlerana UI iş parçacığı için herhangi bir yazı için genellikle yararlı olduğu için; TextViewUpdater sınıfınıza hiç bağlı değil. Bu kodun geri kalanından uzaklaştıracağım ve başka yerlerde de kullanılabileceğini açıklığa kavuşturacağım ... Kodun geri kalanı şüpheli, çünkü tek bir nesneyi dinamik olarak oluşturmaktan kaçınmak için, tek bir aramanın ne olacağını iki adım setText ve postBu, geçici olarak kullandığınız uzun ömürlü bir nesneye dayanır. Gereksiz karmaşıklık ve dişli güvenli değil. Bakımı kolay değil. - ToolmakerSteve
Eğer sen Gerçekten mi bunun bir çok kez çağrıldığı bir durum var, bu önbelleklemeye değer uiHandler ve textViewUpdatersonra sınıfınızı public void setText(String txt, Handler uiHandler) ve yöntem satırı ekleme uiHandler.post(this);  Sonra arayan tek adımda yapabilir: textViewUpdater.setText("Hello", uiHandler);. Daha sonra, eğer iş parçacığı güvenli olması gerekiyorsa, yöntem, bir kilit içindeki ifadelerini sarmalayabilir uiHandlerve arayan değişmeden kalır. - ToolmakerSteve
Eminim ki sadece bir Runnable'ı çalıştırabilirsin. Hangi kesinlikle size fikir kırmak, hangi genel olarak güzel. - Nativ
@Nativ Nope, Runnable birden çok kez çalıştırılabilir. Bir iş parçacığı olamaz. - Zbyszek


Fragmentte kullanmanız gerekiyorsa kullanmalısınız

private Context context;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        this.context = context;
    }


    ((MainActivity)context).runOnUiThread(new Runnable() {
        public void run() {
            Log.d("UI thread", "I am the UI thread");
        }
    });

yerine

getActivity().runOnUiThread(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

Çünkü çağrı cihazı parçası gibi bazı durumlarda boş gösterici istisnası olacak


2
2018-04-28 14:32





merhaba çocuklar bu bir soru sormak

kullanım Handler 

new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});

2
2018-06-01 04:50



RunOnUiThread üzerinden genel amaçlı Handler'ı kullanmayı tercih etmenizin bir sebebi var mı? - ThePartyTurtle


Android P'den itibaren kullanabilirsiniz getMainExecutor():

getMainExecutor().execute(new Runnable() {
  @Override public void run() {
    // Code will run on the main thread
  }
});

İtibaren Android geliştirici dokümanları:

Bu bağlamla ilişkili ana iş parçacığı üzerinde görevlendirilmiş görevleri çalıştıracak bir Yürütücü döndürün. Bu, uygulama bileşenlerine (faaliyetler, hizmetler, vb.) Çağrı göndermek için kullanılan iş parçacığıdır.

İtibaren CommonsBlog:

İşleri ana uygulama iş parçacığında yürütecek bir Yürütücü almak için bağlamda getMainExecutor () öğesini çağırabilirsiniz. Bunu, Looper ve özel bir Executor uygulamasını kullanarak gerçekleştirmenin başka yolları vardır, ancak bu daha basittir.


1
2018-03-09 03:54