2012-04-20 26 views
7

這裏的初始化是我的代碼:最後的局部變量可能沒有在匿名內部類

final Foo myFoo = new Foo(new Inner() { 
    @Override 
    callback(){ 
     myFoo.bar(); 
    } 
}); 

(用實際函數名)

final MyArrayAdapter aa = new MyArrayAdapter(new View.OnClickListener() { 
    @Override 
    onClick(){ 
     aa.notifyDataSetChanged(); 
    } 
}); 

的Java是給我有關錯誤如何myFoo可能尚未初始化。有沒有什麼辦法解決這一問題?當我構造對象然後改變它時,我可以將回調函數設置爲null,但是我希望有一個更清晰的方法。有任何想法嗎? (如果Foo不是由我寫的,並且沒有公開接口來改變回調以後,那麼這將不起作用)

如果任何人都好奇,在我的具體情況下,Foo是一個ArrayAdapter,並且bar是notifyDataSetChanged()。適配器顯示的內容取決於數組中項目的值,而這些值在點擊時會發生變化。回調是clickListener。

+1

你能剛:

class CallbackHelper { private Foo foo; public void setFoo(Foo f){ foo = f; } public Foo getFoo(){ return foo; } } 

,然後用它像這樣請參閱_this.bar()_或_bar()_? – 2012-04-20 01:33:04

+0

不,我的實際代碼比這個例子更復雜,並且回調在另一個匿名內部類中 – Drew 2012-04-20 02:08:07

+0

爲什麼要重寫notifyDataSetChanged?從API文檔看來,您應該調用myFoo.registerDataSetObserver(new DataSetObserver(){})。 – sharakan 2012-04-20 02:27:01

回答

6

簡單的答案是,你絕對不能在Java中這樣做,但編譯器已經告訴過你。你試圖一次創建兩個對象並引用對方,這是一個雞和雞蛋的問題。底線,你必須先創建其中一個。

一個建議是一個兩個步驟的創建:

.... 
final MyArrayAdapter aa = new MyArrayAdapter(); 
aa.initializeButtonClickListener(); 
.... 

然後添加「初始化」方法到適配器。

public void initializeButtonClickListener(){ 
    this.button.setOnClickListener(new View.OnClickListener() { 
     @Override 
     onClick(){ 
      notifyDataSetChanged(); 
     } 
    }); 
} 

由於該建築是有點複雜的(即不是簡單地調用構造更復雜),我建議你再揪到一個MyArrayAdapter工廠方法這兩條線,並且使構造私有。

+0

後設置聽衆的解決方案一樣難看,我明白爲什麼這是不可能的。我重寫了它以在創建第一個對象後設置回調。我不知道爲什麼我不應該調用notifyDataSetChanged(),但我想在數組中的一個元素髮生更改時重新繪製所有內容。 – Drew 2012-04-20 03:58:54

+0

嗯......我想我在你的例子中被名字弄糊塗了。我認爲Inner是一個DataSetObserver,被Adapter調用,不會調用它。 ClickListener(即Inner)正在偵聽的對象在哪裏?我認爲會有三行:創建一個ArrayAdapter,創建一個調用.notifyDataSetChanged的ClickListener,然後創建一個'Clickable'(一個視圖,我想)使用ArrayAdapter作爲'model'的對象,然後調用view.setOnClickListener (聽衆)來完成這個圈子。 – sharakan 2012-04-20 12:11:01

+0

好吧我添加了一個與我的實際場景的版本。 clicklistener所連接的按鈕位於適配器內部。 – Drew 2012-04-20 17:25:02

0

你可以在包含類聲明的方法callBarOnMyFoo和回調調用它:

void callBarOnMyFoo() { 
    myFoo.bar(); 
} 

然後您的回調需要調用callBarOnMyFoo,這是外部類的一個實例方法,其Inner代碼應該有一個引用(我忘記它的語法)。

+0

儘管myFoo是一個本地變量,並且callBarOnMyFoo將無法訪問它。我想我可以把它變成一個成員,但是這似乎與我在建立 – Drew 2012-04-20 02:10:17

3

這將在一般和不接入Inner定義的工作,但你需要創建一個輔助類:不

final CallbackHelper cbh = new CallbackHelper(); 
Foo myFoo = new Foo(new Inner() { 
    @Override 
    callback(){ 
     cbh.getFoo().bar(); 
    } 
}); 
cbh.setFoo(myFoo);