2011-11-08 19 views
2

我嘗試使用反射來爲目標api級別7的應用程序使用自定義列表視圖。必需的文件只能從api級別9獲得,因此我試圖通過反射來解決此問題。我需要找到受保護的方法View.overScrollBy(int,int,int,int,int,int,int,int,boolean)。當我打電話Android中的反射無法正常工作

View.getDeclaredMethods() 

和迭代方法[]數組我找到它,但是當我嘗試

View.class.getDeclaredMethod(String name, Class...<?> paramTypes) 

我得到一個NoSuchMethodException。我比較了從方法提取的值硬編碼的方法名稱和參數類型的值(通過迭代找到),他們是相同的......

private boolean initCompatibility() 
{ 
Method[] methods = View.class.getDeclaredMethods(); 
try { 
    // The name of the Method i am looking for; 
    String OVERSCROLL_S = "overScrollBy"; 
    for (Method meth : methods) { 
     if (meth.getName().equals(OVERSCROLL_S)) { 
      mListView_overScrollBy = meth; 
      break; 
      // method found 
     } 
    } 

    // Params for getDeclaredMethod(…) 
    String methodName = "overScrollBy"; 
    Class[] methodParams = { Integer.TYPE, Integer.TYPE, Integer.TYPE, 
      Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE, 
      Integer.TYPE, Boolean.TYPE }; 

    // works 
    Method test = View.class.getDeclaredMethod(methodName,methodParams); 
    // fails 
    View.class.getDeclaredMethod(mListView_overScrollBy.getName(), 
       mListView_overScrollBy.getParameterTypes()); 

    /* 
    * I also tried this way around and again the first worked and the second 
    * failed, so the input arguments are not the problem... 
    * View.class.getDeclaredMethod(mListView_overScrollBy.getName(), 
    *       mListView_overScrollBy.getParameterTypes()); 
    * Method test = View.class.getDeclaredMethod(methodName,methodParams); 
    */ 

    return true; 
    } catch (SecurityException e) { 
     e.printStackTrace(); 
     return false; 
    } catch (NoSuchMethodException e) { 
     e.printStackTrace(); 
     return false; 
    } 
} 

我不明白爲什麼總是調用工作在第一時間和不是第二次。有趣的是,當我僅爲View.class.getDeclaredMethod(String name,Class ... <?> paramTypes)調用一次時,它也失敗,無論我使用硬編碼輸入值還是從方法中提取的輸入值都沒有任何區別我在尋找...

有沒有人知道問題是什麼?謝謝

+0

看看我的答案。你能否確認在調試和運行模式下是否拋出異常? –

+0

愚蠢的問題時間!這是你正在運行的真實代碼嗎?你以前調查過的「視圖」有沒有可能是一個不同的類,然後呢?不同的'import',因爲它是一個普通的類名。 – Gray

+0

另一個愚蠢的問題:你在printStackTrace上得到一個輸出嗎?我只是在模擬器中運行你的確切代碼,並沒有得到輸出。此外,在eclipse中調試Android應用程序時,行號esp。退貨不正確。因此,在第二個getDeclaredMethod之後,即使沒有異常拋出,IP也會指向catch塊中的return語句! (經常遇到此類行爲) –

回答

1

這非常有趣,但它不是Android專用的,我認爲。

我寫在普通的Java這個小測試:

public class ReflectionTest { 

     public static void main(String[] args){ 
      Method[] m = ReflectionTest.class.getDeclaredMethods(); 
      for (Method method : m) { 
       System.out.println(method.getName()); 
      }    

      try { 
       Method m1 = ReflectionTest.class.getDeclaredMethod("d0", int.class, boolean.class); 
       if(m1 != null){ 
        System.out.println("m1 found!"); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      try { 
       Method m2 = ReflectionTest.class.getDeclaredMethod("d0", Integer.TYPE, Boolean.TYPE); 
       if(m2 != null){ 
        System.out.println("m2 found!"); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      try { 
       Class<?>[] carr = m[1].getParameterTypes(); 
       Method m3 = ReflectionTest.class.getDeclaredMethod("d0", carr); 
       if(m3 != null){ 
        System.out.println("m3 found!"); 
       } 
      } catch (Exception e){ 
       e.printStackTrace(); 
      } 
     } 

     public void d0(int a, boolean b){ 

     } 
    } 

在Eclipse,如果我調試它,三個M1,M2和M3被打印。但是,如果我運行它,嘗試獲取m3時會拋出NoSuchMethodException

更新:

  • 測試linux下JRE 7上運行,並且所有三個M1,M2和M3進行打印。也許是jre6的問題?或者是eclipse運行配置?
  • 如Gray所示,更改carr聲明使用方法0而不是1:Class<?>[] carr = m[0].getParameterTypes();。現在它運行正常,但在調試模式下拋出異常。這意味着返回數組m的方法順序不同。
  • 更新#2確認,我已經包含一個for循環來打印方法名稱。與運行模式相比,方法陣列的順序與調試模式相反。
+0

在MacOSX下,您的測試適用於JRE6下的我。也許一個特定的JRE版本號? – Gray

+0

有同樣的問題:在eclipse中調試時工作,運行時拋出異常。 Win7 64bit,JRE 1.6.0_26-b03和JDK 1.6.0_20-b02。 getDeclaredMethods必須有問題,因爲它搜索'd0([Ljava.lang。字符串)',所以一個String []參數 –

+0

@Gray的方法可能是這種情況。我正在運行JRE 1.6.0_07-b06,eclipse 3.6 helios,Windows XP 32bit。 –

相關問題