2012-01-18 137 views
4

好吧,我read around並且看到Java只通過值傳遞,而不是通過引用,所以我不知道如何實現這一點。通過引用多個Spinner的setOnItemSelectedListener傳遞字符串變量

  • 我有6個Spinners在Android Activity中被填充了不同的SQLite查詢。
  • 填充每個Spinner並設置OnItemSelectedListener的代碼非常相似,所以我希望重構爲一個方法,並使用每個Spinner ID和Sqlite查詢調用它6次。
  • 如何獲得微調onItemSelectedListener更改每個不同微調器上的正確實例成員?

    public void fillSpinner(String spinner_name, final String field_name) { 
    // This finds the Spinner ID passed into the method with spinner_name 
    // from the Resources file. e.g. spinner1 
    int resID = getResources().getIdentifier(spinner_name, "id", 
         getPackageName()); 
    Spinner s = (Spinner) findViewById(resID); 
    final Cursor cMonth; 
    // This gets the data to populate the spinner, e.g. if field_name was 
    // strength = SELECT _id, strength FROM cigars GROUP BY strength 
    cMonth = dbHelper.fetchSpinnerFilters(field_name); 
    startManagingCursor(cMonth); 
    String[] from = new String[] { field_name }; 
    int[] to = new int[] { android.R.id.text1 }; 
    SimpleCursorAdapter months = new SimpleCursorAdapter(this, 
         android.R.layout.simple_spinner_item, cMonth, from, to); 
    months.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
    s.setAdapter(months); 
    // This is setting the Spinner Item Selected Listener Callback, where 
    // all the problems happen 
    s.setOnItemSelectedListener(new OnItemSelectedListener() { 
        public void onItemSelected(AdapterView<?> parent, View view, 
          int position, long id) { 
         Cursor theCursor = (Cursor) parent.getSelectedItem(); 
         // This is the problem area. 
         object_reference_to_clas_member_of_field_name = theCursor 
           .getString(theCursor.getColumnIndex(field_name)); 
        } 
    
        public void onNothingSelected(AdapterView<?> parent) { 
         // showToast("Spinner1: unselected"); 
        } 
    }); 
    

    }

調用此方法像這樣fillSpinner("spinner1","strength");

它找到編號爲spinner1的微調框並在數據庫中查詢strength字段。 field_name,這個例子中的強度必須被聲明爲在onItemSelectedListener中使用的最終變量,否則我會得到錯誤Cannot refer to a non-final variable field_name inside an inner class defined in a different method

但是,如何在使用每個不同的Spinner時,如何讓onItemSelectedListener更改不同實例成員的值?這是所有重要的代碼行:

我不能使用最終的字符串,因爲當用戶選擇不同的值時,變量顯然會改變。我已經讀了很多,很難找到解決方案。我可以複製並粘貼這段代碼6次,忘掉重構,但我真的很想知道這個優雅的解決方案。如果你不明白我的問題,請發表評論,我不確定我是否能夠很好地解釋自己。

+0

實際上,目前尚不清楚你想要什麼,什麼問題你都面臨着onItemSelected。請詳細說明。 – jeet 2012-01-18 04:59:30

+0

'不能在不同的方法中定義的內部類中引用非最終變量field_name',爲什麼不在主類中全局聲明'field_name'。 – 2012-01-21 04:35:24

回答

1

你可以做到這一點,通過傳遞額外類爲fillSpinner方法的參數:

A.創建interface

public interface OnSpinnerValueSelected { 
    void onValueSelected(String selectedValue); 
} 

B.更改方法的位:

public void fillSpinner(String spinner_name, final String field_name, 
        final OnSpinnerValueSelected valueChangeListener) { 

    // Prepare spinner 

    s.setOnItemSelectedListener(new OnItemSelectedListener() { 

     public void onItemSelected(AdapterView<?> parent, View view, 
        int position, long id) { 
      Cursor theCursor = (Cursor) parent.getSelectedItem(); 

      valueChangeListener.onValueSelected(theCursor 
          .getString(theCursor.getColumnIndex(field_name))); 
     } 

     public void onNothingSelected(AdapterView<?> parent) { 

     } 
    }); 
} 

C.提供監聽器:

fillSpinner("spinner1","strength", new OnSpinnerValueSelected() { 
    public void onValueSelected(String selectedValue) { 
     yourObject.setField(selectedValue); 
    } 
}); 
+0

太棒了,這個工作,似乎比在重構函數本身有硬編碼變量名稱更好。所以在Java中你不能通過引用傳遞一個String對象,但是你可以傳遞一個最終對象,它有一個方法來設置String對象的值。 – georgiecasey 2012-01-21 14:38:25

1

將您的聽衆重構爲新的「課程」。根據需要使用正確的參數/實例進行初始化,以便重複的「代碼」可重複使用。

+0

是的,這聽起來很正確。我會嘗試並報告,歡呼 – georgiecasey 2012-01-18 14:27:37

0

對,這就是我如何管理它,但我仍然接受新的建議,以接受答案,我也創造了一個賞金。

我沒有建立像panzerschreck這樣的新課程,所以我將這個作爲新答案發布給我自己的問題。一個黑客的位,但我只是在偵聽器中創建了一個if..then..else語句,以檢查選擇哪個微調器,然後設置不同的實例成員。

s.setOnItemSelectedListener(new OnItemSelectedListener() { 
     public void onItemSelected(AdapterView<?> parent, View view, 
       int position, long id) { 
      Cursor theCursor = (Cursor) parent.getSelectedItem(); 
      if (field_name.equalsIgnoreCase("strength")) { 
       strength=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } else if (field_name.equalsIgnoreCase("ring")) { 
       ring_gauge=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } else if (field_name.equalsIgnoreCase("country")) { 
       country=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } else if (field_name.equalsIgnoreCase("wrapper")) { 
       wrapper=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } else if (field_name.equalsIgnoreCase("length")) { 
       length=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } else if (field_name.equalsIgnoreCase("price")) { 
       price=theCursor.getString(theCursor.getColumnIndex(field_name)); 
      } 
      // showToast(category); 
     } 

     public void onNothingSelected(AdapterView<?> parent) { 
      // showToast("Spinner2: unselected"); 
     } 
    }); 

下面是類成員

private String strength,ring_gauge,country,wrapper,length,price; 

黑客的Java位,但沒有允許對象通過引用傳遞真的,這是我所能做的。

+1

我必須說它不是一個很好的做法,如果'陳述。儘可能避免硬編碼值,這是一個維護噩夢! – panzerschreck 2012-01-19 03:30:46

+0

如果這就是你的意思,我無法在字符串上使用switch語句。我知道,我不想使用硬編碼值,但還有其他選擇。我很想知道這個優雅的解決方案。我嘗試創建一個新的類作爲你建議的監聽器,但問題是我如何通過引用傳遞實例成員,而不是通過值來傳遞這個新監聽器類的構造函數。 – georgiecasey 2012-01-19 03:50:37