AsyncTask'a birden çok ilkel parametreyi nasıl iletebilirsiniz?


82

Gibi ilgili soru vardır bir AsyncTask sınıfına 2 parametrelerinde geçebilir nasıl? , ancak bir AsyncTask'a parametre olarak birden çok ilkeli aktarmayı boşuna denemenin zorluğuyla karşılaştım, bu yüzden keşfettiğim şeyi paylaşmak istiyorum. Bu incelik, mevcut soru ve cevaplarda yer almıyor, bu yüzden benimle aynı problemle karşılaşan herkese yardım etmek ve onları acıdan kurtarmak istiyorum.

Soru şudur: Arka planda yürütülecek bir AsyncTask'a iletmek istediğim birden çok ilkel parametrem var (örneğin, iki uzun) - nasıl yapılabilir? (Cevabım ... bununla bir süre uğraştıktan sonra ... aşağıda bulunabilir.)


Yanıtlar:


154

Temel öğelerinizi basit bir kaba sarın ve bunu bir parametre olarak AsyncTaskşunun gibi iletin:

private static class MyTaskParams {
    int foo;
    long bar;
    double arple;

    MyTaskParams(int foo, long bar, double arple) {
        this.foo = foo;
        this.bar = bar;
        this.arple = arple;
    }
}

private class MyTask extends AsyncTask<MyTaskParams, Void, Void> {
    @Override
    protected void doInBackground(MyTaskParams... params) {
        int foo = params[0].foo;
        long bar = params[0].bar;
        double arple = params[0].arple;
        ...
    }
}

Şöyle diyelim:

MyTaskParams params = new MyTaskParams(foo, bar, arple);
MyTask myTask = new MyTask();
myTask.execute(params);

Bu da işe yarar. Ancak yukarıdaki seçeneklerin daha basit olduğuna inanıyorum.
robguinness

10
Bu aslında bana çok daha hoş geliyor. Object ... params yöntemini kullanıyorum ve bazı nedenlerden dolayı bunu yapmak iyi ya da güvenli hissetmiyor.
Mafro34

1
Cazibeli dost gibi çalışıyor ... Paylaştığın için teşekkürler ..!
Deepak S. Gavkar

2
Çok zarif, bayıldım.
Sipty

1
@DavidWasser: güncellemeniz için teşekkürler, verilen çözümün yanı sıra harika çalışıyor!
Moussa

93

Başka bir yol: MyTask sınıfınıza MyTask kurucusunu eklemeniz yeterlidir:

private class MyTask extends AsyncTask<String, Void, Void> {
    int foo;
    long bar;
    double arple;

    MyTask(int foo, long bar, double arple) { 
         // list all the parameters like in normal class define
        this.foo = foo;
        this.bar = bar;
        this.arple = arple;
    }
    ......   // Here is doInBackground etc. as you did before
}

Sonra ara

new MyTask(int foo, long bar, double arple).execute();

David Wasser'in Yanıtı gibi ikinci bir yol.


9
aslında bu, üçünün farklı türden argümanları iletmek için en sevdiğim yoludur. Yayınlanacak Nesne yok ve ek bir sınıf oluşturmaya gerek yok.
QuickFix

3
Geçersiz kılınan kurucunuzda super () çağırmanız gerekir!
zyamys

2
@zyamys burada super () neden gerekli? Anladığım kadarıyla otomatik olarak çağrılacak. Buraya bakın stackoverflow.com/a/2054040/984263
carthurs

Bu konudaki seçeneklerden en iyisi bunu seviyorum. Yardımcı sınıf yok, bu sınıf kendi başına kullanılabilir ve kendi gereksinimlerini açıklar. Etrafta gizemli nesneler geçmiyor. Teşekkürler.
Vinnyq12

Bu çalışıyor. Çok kirli hissediyor ama başka bir şey denemek için çok tembelim. Bunu yerel olarak yapmanın doğal bir yolu olmadığına inanamıyorum. Muhtemelen Java'da daha sonra desteklenebilir<(String,Object,int),Void,Void>
Sirens

82

AsyncTask'a birden çok temel öğe geçirmek (tam anlamıyla) mümkün DEĞİLDİR. Örneğin , ilgili yöntemi gerçekleştirmek myTask.execute(long1, long2)ve ayarlamayı denemek istiyorsanız private class myTask extends AsyncTask<long, Void, Void>:

@Override
protected LocationItemizedOverlay doInBackground(long... params) {...}

IDE'niz büyük olasılıkla bir süper tip yöntemini geçersiz kılmanız gerektiğinden şikayet edecektir. Sözde Varargs yöntem imzasını kullandığınızı unutmayın doInBackground, burada (long... params)"Değişken sayıda longları kabul ediyorum, params adı verilen bir dizi olarak depolanır. Bir derleyicinin / IDE şikayetinin ortaya çıkmasına neyin sebep olduğunu tam olarak anlamıyorum , ancak bunun genel sınıfın nasıl Paramstanımlandığı ile ilgisi olduğunu düşünüyorum .

Her durumda, ilkellerinizi ilgili ilkel olmayan sarmalayıcılara doğru şekilde atmanız koşuluyla (örneğin, int => Tamsayı, uzun => Uzun, vb.) İstediğiniz şeyi sorunsuz bir şekilde elde etmek mümkündür. Aslında, ilkellerinizi ilkel olmayanlara açıkça atmanıza gerek yoktur. Java bunu sizin için hallediyor gibi görünüyor. ASyncTask'inizi aşağıdaki gibi ayarlamanız yeterlidir (uzunlar örneği için):

private class MyTask extends AsyncTask<Long, Void, Void> {

    @Override
    protected void doInBackground(Long... params) {
        // Do stuff with params, for example:
        long myFirstParam = params[0]
    }
    ...
}

Daha sonra bu sınıfı başlangıçta amaçladığınız gibi kullanabilirsiniz, örneğin:

MyTask myTask = new MyTask();
myTask.execute(long1, long2);

Veya istediğiniz herhangi bir sayıda ilkel varlık için, BUNLARIN AYNI TİPTE OLDUĞUNU SAĞLAYIN. Birden fazla ilkel türü geçirmeniz gerekiyorsa, bu da yapılabilir, ancak yukarıdakileri şu şekilde değiştirmeniz gerekecektir:

private class MyTask extends AsyncTask<Object, Void, Void> {

    @Override
    protected void doInBackground(Object... params) {
        // Do stuff with params, for example:
        long myLongParam = (Long) params[0];
        int myIntParam = (Integer) params[1];

    }
    ...
}

Bu daha esnektir, ancak parametrelerin açıkça ilgili türlerine dönüştürülmesini gerektirir. Bu esnekliğe ihtiyaç yoksa (yani tek bir veri türü), biraz daha okunaklı olduğu için ilk seçeneğe bağlı kalmanızı öneririm.


Ayrıca yöntem için aşağıdakileri kullanabilir ve protected LocationItemizedOverlay doInBackground(Object[] objects) zaman uyumsuz görev tanımı için aşağıdakileri ekleyebilirsiniz. private class MyTask extends AsyncTask<Object, Void, Void>
Hany Sakr

8

Yerleşik yürütme yöntemi bir Param dizisini kabul eder , ancak bunların hepsi tanımlı türde olmalıdır. Bu nedenle, PARAM türünü basitçe OBJECT olarak ayarlarsanız , o zaman istediğiniz her şeyi nesnelerin çocukları olduğu sürece aktarabilirsiniz. ...

private class MyTask extends AsyncTask<Object, Void, Void> {

Daha sonra doInBackGround'unuzda, ihtiyacınız olan şeye geri dönmek için her bir parametreyi atarsınız:

 @Override
 protected void doInBackground(Object... params) {
     Context t = (Context)params[0];
     String a = (String) params[1];
     List<LatLng> list = (List<LatLng>)params[2];
     .
     .
     .

Ve uygulamanız basitçe:

 new MyTask().execute(context,somestring,list_of_points);

Siparişi her iki tarafa da bağlı olduğunuz için kendi paketleyici sınıfınıza veya bir pakete veya karma veya başka bir şeye sarmak kadar iyi bir form değil, ancak işe yarayacaktır. Elbette dizinizi HashMap (,) parametresinin bir parametresi haline getirebilirsiniz ve bu noktada temelde özel bir paket uyguluyorsunuz, ancak işe yarayacak.


1
Buradaki insanlar pek çok harika teknikle çok havalılar ve bu benim favorimdi!
George Udosen

7

Malajisi'nin yöntemini seviyorum, ama istemediyseniz Bundle sınıfını kullanamaz mıydınız?

 Bundle myBundle = new Bundle();
 myBundle.putInt("foo", foo);
 myBundle.putLong("bar", bar);
 myBundle.putDouble("arple", arple);

Ardından paketi verin ve MyTask'ın içinde açın. Bu berbat bir fikir mi? Özel bir sınıf oluşturmaktan kaçınırsınız ve daha sonra ek parametreleri iletmeniz gerektiğine karar verirseniz bu esnektir.

Güncelleme: Bu cevabı yazalı epeyce yıl oldu ve şimdi gerçekten hoşuma gitmiyor. Bir Bundle kullanmamanızı tavsiye ederim. Bir eşzamansız göreve (veya herhangi bir şeye) birden fazla parametre aktarmanız gerekiyorsa, tüm parametrelerinizi aynı anda tutan özel bir sınıf kullanın. Bir paket kullanmak, sahip olmamanız gereken bir soruna iyi bir çözümdür. Tam olarak ihtiyacınız olanı tutmak için özel bir sınıf oluşturmaya karşı bir yasa yoktur, başka hiçbir şey yoktur.

Ayrıca, neden eşgüdüm kullanmıyorsunuz? Asenkron görevler çok 2014.


İyi fikir. Ben bu özel desteklemek doInBackground () içine geçirilen nesneleri etmediği konusunda varsayalım
John Ward

1

Bu, alt sınıflandırma yoluyla çözülür. Google'ın resmi Android AsyncTask Belgelerinde bu sorunu çözmek için (alt sınıflandırma) bir örneği vardır:

http://developer.android.com/reference/android/os/AsyncTask.html

Misal:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    protected Long doInBackground(URL... urls) {
        int count = urls.length;
        long totalSize = 0;
        for (int i = 0; i < count; i++) {
            totalSize += Downloader.downloadFile(urls[i]);
            publishProgress((int) ((i / (float) count) * 100));
                 // Escape early if cancel() is called
            if (isCancelled()) break;
        }
        return totalSize;
    }

    protected void onProgressUpdate(Integer... progress) {
        setProgressPercent(progress[0]);
    }

    protected void onPostExecute(Long result) {
        showDialog("Downloaded " + result + " bytes");
    }
}
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.