android - 如何將多個原始參數傳遞給AsyncTask?




android-asynctask primitive variadic-functions (6)

有相關的問題,例如如何將2個參數傳遞給AsyncTask類? ,但是我遇到了徒勞地嘗試將多個原語作為參數傳遞給AsyncTask的困難,所以我想分享我發現的內容。 在現有的問題和答案中沒有捕捉到這種微妙之處,所以我想幫助那些遇到與我一樣的問題的人,並為他們省去痛苦。

問題是:我有多個原始參數(例如兩個long)我想傳遞給AsyncTask以在後台執行 - 它怎麼能完成? (我的回答......經過一段時間的掙扎......可以在下面找到。)


Answers

(嚴格地說)不可能將多個原語傳遞給AsyncTask。 例如,如果要執行myTask.execute(long1, long2)並嘗試設置private class myTask extends AsyncTask<long, Void, Void>使用相應的方法private class myTask extends AsyncTask<long, Void, Void>

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

您的IDE可能會抱怨需要覆蓋超類型方法。 請注意,您正在為doInBackground使用所謂的Varargs方法簽名,其中(long... params)就像是說“我接受一個可變數量的long,存儲為一個名為params的數組。我不完全理解是什麼原因要引發的編譯器/ IDE投訴,但我認為它與如何定義泛型類Params

在任何情況下,只要您正確地將基元轉換為各自的非原始包裝器(例如int => Integer,long => Long等),就可以毫無問題地實現您想要的功能。 實際上,您不需要將基元顯式轉換為非基元。 Java似乎為您處理這個問題。 您只需按如下方式設置ASyncTask(以longs為例):

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

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

然後,您可以按照最初的預期使用此類,例如:

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

或者對於你想要的任何數量的原語,提供它們是相同類型的。 如果您需要傳遞多種類型的基元,也可以這樣做,但您需要將上述內容修改為:

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];

    }
    ...
}

這更靈活,但需要將參數明確地轉換為各自的類型。 如果不需要這種靈活性(即單一數據類型),我建議堅持使用第一個選項,因為它更具可讀性。


只需將基元包裝在一個簡單的容器中,並將其作為參數傳遞給AsyncTask,如下所示:

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

這樣叫:

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

內置的execute方法接受Params數組,但它們都必須是定義的類型..因此,如果您只是將PARAM類型設置為OBJECT,那麼只要它們是對象的子項,您就可以傳入任何您喜歡的內容。 ...

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

然後在你的doInBackGround中,你只需按順序投射每個參數,然後回到你需要它的位置:

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

你的執行簡單地說:

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

不像將它包裝在你自己的包裝器類,包或者哈希或其他東西中那樣好,因為你的訂單依賴於雙方,但它會起作用。 當然你可以讓你的數組成為HashMap(,)的一個參數,你基本上是在那時自定義實現一個bundle,但它會工作。


我喜歡malajisi的方法,但如果你沒有,你不能使用Bundle類嗎?

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

然後只需傳遞捆綁包並將其解壓縮到MyTask中。 這是一個糟糕的主意嗎? 您可以避免創建自定義類,如果您決定稍後需要傳遞其他參數,則它很靈活。


這是通過子類化來解決的。 谷歌在官方的Android AsyncTask文檔中有一個解決這個問題(子類)的例子:

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

例:

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

您可以查看Google I / O 2011:Android開發工具談話中的模擬器問題,從0:40:20開始。

模擬器運行緩慢,因為完整的Android環境在模擬硬件上運行,並且指令也在模擬的ARM處理器上執行。

主要的窒息點是渲染,因為它不是在任何專用硬件上運行,而是實際上是通過軟件渲染來執行的。 降低屏幕尺寸將大大提高仿真器性能。 獲得更多/更快的內存無濟於事。

他們當時提到他們正在開發一個接口,允許模擬器通過主機硬件管理某些指令,因此最終你將能夠利用桌面硬件的原始功能來利用模擬器性能。





android android-asynctask primitive variadic-functions