2012-04-20 24 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);