Domanda

My DialogFragment contains an -initially invisible- OK button and a ListView of clickable items. When any of the ListView items is clicked I set button's visibility to VISIBLE.

This is done through an anonymous OnItemClickListener. The code below works but I don't get why. Since Java does not support closures, I would expect the compiler to complain about button not being final.

Isn't this a typical case of a closure? How come the code below doesn't produce a compiler error?

Thank you

public class AlternativeRoomsDialog extends DialogFragment {

private Button okButton;

static AlternativeRoomsDialog newInstance(String name) {
    AlternativeRoomsDialog f = new AlternativeRoomsDialog();
    return f;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_alternative_rooms, container);
    getDialog().setTitle("Change Room");

    ListView lv = (ListView) view.findViewById(R.id.alternative_rooms_list);
    final adapter = /*some initialization*/;
    lv.setAdapter(adapter);
    lv.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View linlay, int position, long id) {
            okButton.setVisibility(View.VISIBLE);
            ListView lv = (ListView) linlay.getParent();
            int total = lv.getChildCount();
            for (int i=0; i< total; i++){
                lv.getChildAt(i).setBackgroundColor(Color.BLUE);
            }
            linlay.setBackgroundColor(Color.GREEN);
        }
    }); 

    // setup OK button
    okButton = (Button) view.findViewById(R.id.btn_ok);
    okButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(AlternativeRoomsDialog.this.getActivity(), "ok button clicked", Toast.LENGTH_SHORT).show();
        }
    });
    return view;
}

}

È stato utile?

Soluzione

The requirement of variables being declared final only applies to local variables, because they are the ones that go out of scope when the method returns. Your button is referenced by a member variable, and there's no need for it to be final: the member won't go anywhere as long as the object exists.

Altri suggerimenti

You don't need to make the instance variable final, that is only the case with local variables. The local variables needs to be final, they are copied to the anonymous class you use inside the method, as instance variables of that class. This is done because the anonymous inner class instance might stay in heap memory, after the method returns. So, it may require to access the variable even after the method stack frame is de-allocated.

Now, since there are 2 copies of the local variables, they can go out of sync, if the local variable is changed outside the anonymous inner class. That would really go weird, that is why it is required to make the local variable final.

As with instance variables, they are instead shared between enclosing class instance, and anonymous inner class instance. So, you don't need to make them final.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top